//========================================================================
//  SE5 Construction - Captain Kwok's Balance Mod v125+
//========================================================================
//
// 1. Remove obsolete items from construction queues
// 2. Calculate resources to spend on construction
// 3. Add facility constructions
//     - Attempt to upgrade facilities
//     - Determine which special facilities might be useful for the colony
//     - Build facilities suited to the colony type
//     - Consider overriding certain facility choices if another facility is more urgently needed
// 4. Add vehicle constructions
//     - Determine which design types are in demand
//     - Determine the best queue to build the selected design type
//     - Complete purchasing when all budgeted resources are spent
//
//  Balance Mod Changes:
//  --------------------
//  v1.29 Changed - AI players will prioritize a Resupply Depot in systems with less than 3 planets (ie asteroid belt systems)
//        Fixed   - It was possible for AI players to sometimes build a Components Factory on a planet with no Space Yard
//  v1.25 Changed - Updates for changes to facility names and addition of Interdimensional facilities and new Psychic facility
//        Added   - Support for Storage Compound colony type
//  v1.21 Fixed   - Removed extra check for temporal space yard facility as the condition already check for the space yard ability
//  v1.20 Changed - Updated design type references
//  v1.19 Changed - Made some improvements to how the AI was adding items to its queues
//        Fixed   - The AI would sometimes add an Atmospheric Modification Planet to convert a Gas Giant to a None atmosphere (v1.19a)
//        Changed - Improved the AI's queue selection for unit construction (v1.19a)
//        Changed - AI colonies in systems with an enemy presence will prioritize unit construction (v1.19a)
//        Changed - Revised colony build lists (v1.19a)
//        Added   - Build lists for ministers acting on behalf of human players (v1.19a)
//        Changed - Made improvements to when the AI removes items from its construction queues (v1.19b)
//        Changed - Replaced research to intel ratio modifier with a percentage based one (v1.19c)
//        Changed - AI will check to see if construction minister for ships or units is active before skipping facility construction on a colony (v1.19c)
//        Changed - Further improvements to the AI's evaluation criteria for removing items from queues to save resources (v1.19c)
//        Fixed   - AI wasn't considering if it had the Natural Merchants trait for Space Port construction (v1.19f)
//        Fixed   - AI was often constructing multiple Ultra-Recycler facilities (v1.19g)
//        Changed - Revised AI's design type demand calculation (v1.19h)
//        Fixed   - AI shouldn't be adding unit items to Space Yard Ship queues (v1.19i)
//        Fixed   - AI had stopped adding ships/units to BSY queues (v1.19j)
//        Changed - Added more support for Finite Resource games and resource facility selection (v1.19j)
//        Fixed   - The AI wasn't adding facility upgrades to colonies that were at maximum amount of facilities (v1.19j)
//        Fixed   - AI would sometimes add Research Center upgrades when already at max tech (v1.19j)
//  v1.18 Fixed   - The AI wasn't using BSYs to construct units very efficiently
//        Changed - Added a slight bump to AI vehicle demand levels when resource surpluses are available
//  v1.15 Added   - Enhanced the AI's ability to remote items from its queues when resources are low
//        Changed - Improved the AI's ability to add multiple items to queues in times of plentiful resources
//        Changed - Improved unit distribution for the AI's colonies
//        Fixed   - Sometimes the AI would build more than 1 of a facility they didn't need
//        Fixed   - The AI was skipping monolith construction when it shouldn't have
//        Fixed   - AI was adding multiple instances of the same upgrades
//        Changed - AI will upgrade all facilities of a type at the same time
//        Added   - AI will not attempt to construct ships or units if at maximum number of ships or units
//        Added   - AI will remove ships or units from its queues if at the maximum number of ships or units
//        Added   - In a low resource situation, the AI might remove non-resource facilities from queues
//  v1.13 Changed - AI can queue up multiple facilities
//  v1.11 Added   - If AI is low on a resource, they won't add new units to the queue
//  v1.10 Changed - Renamed Fx[Add_Planet_Ground_Constructions] to Fx[Add_Facility_Constructions]
//        Changed - Renamed Fx[Get_Ground_Constructions_Percentages] to Fx[Get_Facility_Construction_Percentages]
//        Changed - Planets with no facility space will try to add facilities
//        Fixed   - The AI would sometimes add multiple Spaceports or Resupply Depots to queues in the same system
//        Changed - Revised AI queue purchasing to fill queues more efficiently
//        Fixed   - AI wouldn't always add units if they cost more than the queue's usage rate
//  v1.08 Fixed   - Sometimes facilities weren't being added to the queue due to an error in the maximum per location
//        Changed - If maintenance spending is high, AI will focus more on facility construction
//  v1.07 Added   - Conditions for Research Compounds to add intel facilities
//        Changed - Construction ministers for units and ships would add obsolete designs if no new designs existed for a design type
//  v1.06 Changed - Moved facility_id variables to Script_AI_GlobalSettings.txt
//        Changed - Monolith Facilities will be constructed if available for "Resource Colony" colony type
//        Changed - Added new conditions for calculating resources to spend in Fx[Compute_Spending_Resources]
//        Removed - Fx[Compute_Total_Resources]
//        Fixed   - Error in Fx[Get_Race_Design_Type_To_Purchase] when skipping ships or units for construction
//        Added   - Boolean variables to add needed resource facilities if low on resources in Fx[Get_Ground_Constructions_Percentages]
//        Changed - Separated ships and units for purchasing purposes
//        Added   - Conditions to try and purchase a previously failed purchase
//  v1.05 Changed - Updated facility queue lists in Fx[Get_Ground_Constructions_Percentages]
//        Removed - Parameters in Fx[Get_Race_Design_Type_To_Purchase] to construct defense bases
//        Changed - Queues will add multiple items to take advantage of construction point carry-over
//        Changed - If a unit or ship purchase fails, then AI will not try to add them to the queue again
//        Added   - Fx[Compute_Total_Resources]
//        Added   - Support for Construction Yard colony type
//  v1.04 Changed - Updated Fx[Get_Race_Design_Type_To_Purchase] to new vehicle purchase scheme
//  v1.03 Added   - New functions introduced in SE:V v1.22 to control Spaceport and Space Yard addition
//        Added   - Extended facility in queues scheme to include Resupply Depots
//  v1.02 Fixed   - Occasionally Fx[Add_Vehicle_Constructions] got caught in a long loop
//  v0.97 Added   - Facility lists for new colony types: Mining & Farming, etc.
//  v0.93 Changed - Increased priority for Resupply Depot construction
//  v0.92 Changed - Revised facility lists for colonies
//  v0.84 Added   - Facility list for new colony type: Resource Colony
//
//  Balance Mod To Do List:
//  -----------------------
//  - Nothing pending
//
//  Script Function Requests:
//  -------------------------
//  - Sys_Get_Queue_Setting(queue_id): long (Returns CONSTANT = queue setting)
//  - Sys_Set_Queue_Setting(queue_id, CONSTANT): boolean (CONSTANT = Queue Setting, Returns TRUE if set successful)

//------------------------------------------------------------------------
// Global Constants
//------------------------------------------------------------------------
globalconst

  ITEM_TO_CONSTRUCT_FACILITY:          long := 1
  ITEM_TO_CONSTRUCT_SHIP_DESIGN:       long := 2
  ITEM_TO_CONSTRUCT_UNIT_DESIGN:       long := 3
  ITEM_TO_CONSTRUCT_UPGRADE_FACILITY:  long := 4

endglobalconst

//------------------------------------------------------------------------
// Global Variables
//------------------------------------------------------------------------

globalvars

  gbl_queue_id:              long
  gbl_colony_type:           string

  gbl_queue_units_only:      boolean
  gbl_queue_ships_only:      boolean
  gbl_stop_purchasing:       boolean

  gbl_resources_to_spend:    resources

  gbl_lst_item_type:         longlist
  gbl_lst_item_id:           longlist
  gbl_lst_pct_of_space:      longlist
  gbl_lst_max_per_loc:       longlist

endglobalvars

//------------------------------------------------------------------------
// Forward Declarations
//------------------------------------------------------------------------
deffunc

function Remove_Uneeded_Items returns boolean
params
end

function Check_To_Remove_Items_From_Queue returns boolean
params
  queue_id:                  long
end

function Compute_Spending_Resources returns boolean
params
end

function Add_Facility_Constructions returns boolean
params
end

function Add_Vehicle_Constructions returns boolean
params
end

function Add_Constructions_From_Item_List returns boolean
params
  queue_id:                  long
  max_items:                 long
end

function Add_Specific_Construction_To_Queue returns long
params
  queue_id:                  long
  item_index:                long
  max_items:                 long
end

function Add_Facility_Construction_Percentage returns boolean
params
  facility_id:               long
  percent_of_space:          long
  max_per_loc:               long
  skip_facility:             boolean
end

function Get_Facility_Construction_Percentages returns boolean
params
end

function Get_Race_Design_Type_To_Purchase returns string
params
  skip_unit:                 boolean
  skip_ship:                 boolean
  skip_base:                 boolean
end

enddeffunc

//------------------------------------------------------------------------
// AI_Construction
//------------------------------------------------------------------------
function AI_Construction returns boolean
params
vars
begin

  // Debug output
  call Sys_Debug_Print("Construction", "-------------")
  call Sys_Debug_Print("Construction", "Construction:")

  if Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Queue Cleanup") then
    call Remove_Uneeded_Items()
  endif

  if Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Facilities") or Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Ships") or Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Units") then
    call Compute_Spending_Resources()
  endif

  if Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Facilities") then
    call Add_Facility_Constructions()
  endif

  if Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Ships") or Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Units") then
    call Add_Vehicle_Constructions()
  endif

end

//------------------------------------------------------------------------
// Remove_Uneeded_Items
//------------------------------------------------------------------------
function Remove_Uneeded_Items returns boolean
params
vars
  index:                     long
  list_count:                long
  lst_queues:                longlist
begin

  // Get a list of our construction queues
  call Sys_Get_List_Of_Players_Construction_Queues(sys_long_Player_ID, lst_queues)

  // Debug output
  call Sys_Debug_Print("Construction", "----------------------------")
  call Sys_Debug_Print("Construction", "Construction - Queue Status:")

  // Remove items from our queues that are not needed or to save resources
  set list_count := lst_queues.count()

  if (list_count > 0) then
    for index := 1 to list_count do
      call Check_To_Remove_Items_From_Queue(lst_queues.get(index))
    endfor
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Check_To_Remove_Items_From_Queue
//------------------------------------------------------------------------
function Check_To_Remove_Items_From_Queue returns boolean
params
  queue_id:                  long
vars
  lst_queue_items:           longlist
  list_count:                long
  index:                     long
  remove_item:               boolean
  remove_all_items:          boolean
  item_space:                long
  remaining_space:           long
  item_id:                   long
  item_name:                 string
  item_cost:                 resources
  item_minerals:             real
  item_organics:             real
  item_radioactives:         real
  resources_spent:           resources
  spent_minerals:            real
  spent_organics:            real
  spent_radioactives:        real
  remaining_minerals:        real
  remaining_organics:        real
  remaining_radioactives:    real
  queue_item_id:             long
  queue_item_type:           long
  queue_rate:                resources
  pct_completed:             long
  max_pct_completed:         long := 50
  queue_name:                string
begin

  // Get a list of items in our active construction queues
  call Sys_Get_Construction_Queue_Items_List(queue_id, lst_queue_items)

  // Get the queue's details
  set queue_name := Sys_Get_Space_Object_Name(queue_id)
  set queue_rate := Sys_Get_Construction_Queue_Resource_Usage_Rate(queue_id)

  // Debug output
  call Sys_Debug_Print("Construction", "  - " + queue_name + ":")

  // If our queue rate is zero, remove all items
  if (queue_rate.get(RESOURCE_TYPE_MINERALS) <= 0) then
    set remove_all_items := TRUE
    // Debug output
    call Sys_Debug_Print("Construction", "    - Removed all items since it can't build anything")
  endif

  // Go through the queued items
  set list_count := lst_queue_items.count()

  if (list_count > 0) then
    set index := 0
    // Go through our items in the queue to see if any can be removed
    loop
      set index := index + 1
      set remove_item := FALSE
      set queue_item_id := lst_queue_items.get(index)
      set queue_item_type := Sys_Get_Construction_Queue_Item_Type(queue_id, queue_item_id)

      // How much have we spent on the item?
      set resources_spent := Sys_Get_Construction_Queue_Item_Completed_Resources(queue_id, queue_item_id)
      set spent_minerals := resources_spent.get(RESOURCE_TYPE_MINERALS)
      set spent_organics := resources_spent.get(RESOURCE_TYPE_ORGANICS)
      set spent_radioactives := resources_spent.get(RESOURCE_TYPE_RADIOACTIVES)

      // Set the max completed percent amount to drop an item
      if Sys_Is_Construction_Queue_Item_Unit(queue_id, queue_item_id) then
        set max_pct_completed := 100
      else
        set max_pct_completed := 50
      endif

      if (not remove_all_items) then
        if (queue_item_type = CONSTRUCTION_ITEM_TYPE_VEHICLE_DESIGN) then
          // Get the item's details
          set item_id := Sys_Get_Construction_Queue_Item_Design_ID(queue_id, queue_item_id)
          set item_cost := Sys_Get_Vehicle_Design_Cost(item_id)
          set item_name := Sys_Get_Vehicle_Design_Name(item_id) + " [" + Sys_Get_Vehicle_Design_General_Type(sys_long_player_ID, item_id) + "]"
          set item_minerals := item_cost.get(RESOURCE_TYPE_MINERALS)
          set item_organics := item_cost.get(RESOURCE_TYPE_ORGANICS)
          set item_radioactives := item_cost.get(RESOURCE_TYPE_RADIOACTIVES)
          set remaining_minerals := item_minerals - spent_minerals
          set remaining_organics := item_organics - spent_organics
          set remaining_radioactives := item_radioactives - spent_radioactives
          // How complete is the construction?
          if (item_minerals + item_organics + item_radioactives > 0) then
            set pct_completed := Sys_Trunc((spent_minerals + spent_organics + spent_radioactives) / (item_minerals + item_organics + item_radioactives) * 100)
          else
            set pct_completed := 0
          endif

          // Remove ships/units from the queue if we are at max ship/unit limit
          if Sys_Is_Construction_Queue_Item_Unit(queue_id, queue_item_id) then
            if (bool_Race_At_Max_Units) then
              set remove_item := TRUE
              // Debug output
              call Sys_Debug_Print("Construction", "    - Removed unit from queue (Max Units)")
            endif
          else
            if (bool_Race_At_Max_Ships) then
              set remove_item := TRUE
              // Debug output
              call Sys_Debug_Print("Construction", "    - Removed ship from queue (Max Ships)")
            endif
          endif

          // Remove ships/units from the queue if we are low on resources and they are not complete
          if (pct_completed < max_pct_completed) then
            if ((bool_Race_Minerals_Low) and (remaining_minerals > 100.0)) or ((bool_Race_Organics_Low) and (remaining_organics > 100.0)) or ((bool_Race_Radioactives_Low) and (remaining_radioactives > 100.0)) then
              set remove_item := TRUE
              // Debug output
              call Sys_Debug_Print("Construction", "    - Removed item from queue (Low Resources)")
            endif
          endif

          // Remove units from the queue if there is no space for them
          if (not remove_item) then
            if Sys_Is_Construction_Queue_Item_Unit(queue_id, queue_item_id) and (not Sys_Is_Space_Object_Base(queue_id)) then
              set item_space := Sys_Get_Construction_Queue_Item_Total_Tonnage_Space(queue_id, queue_item_id)
              set remaining_space := Sys_Get_Space_Object_Cargo_Space_Remaining(queue_id)
              // Not enough space?
              if (item_space > remaining_space) then
                set remove_item := TRUE
                // Debug output
                call Sys_Debug_Print("Construction", "    - Removed item from queue (No Cargo Space)")
              endif
            endif
          endif
        endif

        // Remove non-resource facilities from the queue if we are low on resources
        if (queue_item_type = CONSTRUCTION_ITEM_TYPE_FACILITY) then
          set item_id := Sys_Get_Construction_Queue_Item_Facility_ID(queue_id, queue_item_id)
          set item_name := Sys_Get_Facility_Name(item_id)
          set item_cost := Sys_Get_Facility_Cost(sys_long_Player_ID, item_id)
          set item_minerals := item_cost.get(RESOURCE_TYPE_MINERALS)
          set item_organics := item_cost.get(RESOURCE_TYPE_ORGANICS)
          set item_radioactives := item_cost.get(RESOURCE_TYPE_RADIOACTIVES)
          set remaining_minerals := item_minerals - spent_minerals
          set remaining_organics := item_organics - spent_organics
          set remaining_radioactives := item_radioactives - spent_radioactives
          set pct_completed := Sys_Trunc(Sys_Resources_Divide(resources_spent, item_cost)) * 100

          // Remove uncompleted facilities that are using resources that are scarce, but don't remove needed resource facilities
          if (pct_completed < max_pct_completed) then
            // Minerals
            if (bool_Race_Minerals_Low) and (bool_Race_Minerals_Deficit) and (remaining_minerals > 100.0) then
              if (item_id <> lng_facility_id_minerals) and (item_id <> lng_facility_id_monolith) and (item_id <> lng_facility_id_solar_resources) and (item_id <> lng_facility_id_minerals_mod) and (item_id <> lng_facility_id_minerals_sys_mod) then
                set remove_item := TRUE
                // Debug output
                call Sys_Debug_Print("Construction", "    - Removed " + item_name + " to save minerals")
              endif
            endif
            // Organics
            if (bool_Race_Organics_Low) and (bool_Race_Organics_Deficit) and (remaining_organics > 100.0) then
              if (item_id <> lng_facility_id_organics) and (item_id <> lng_facility_id_monolith) and (item_id <> lng_facility_id_solar_resources) and (item_id <> lng_facility_id_organics_mod) and (item_id <> lng_facility_id_organics_sys_mod) then
                set remove_item := TRUE
                // Debug output
                call Sys_Debug_Print("Construction", "    - Removed " + item_name + " to save organics")
              endif
            endif
            // Radioactives
            if (bool_Race_Radioactives_Low) and (bool_Race_Radioactives_Deficit) and (item_radioactives > 100.0) then
              if (item_id <> lng_facility_id_radioactives) and (item_id <> lng_facility_id_monolith) and (item_id <> lng_facility_id_solar_resources) and (item_id <> lng_facility_id_radioactives_mod) and (item_id <> lng_facility_id_radioactives_sys_mod) then
                set remove_item := TRUE
                // Debug output
                call Sys_Debug_Print("Construction", "    - Removed " + item_name + " to save radioactives")
              endif
            endif
            // Don't remove Space Ports!
            if (item_id = lng_facility_id_spaceport) then
              set remove_item := FALSE
            endif
          endif
        endif

        // Remove facility upgrades for facilities that are non-existent
        if (queue_item_type = CONSTRUCTION_ITEM_TYPE_UPGRADE_FACILITY) then
          set item_id := Sys_Get_Construction_Queue_Item_Upgrade_ID(queue_id, queue_item_id)
          set item_name := Sys_Get_Facility_Name(item_id)
          // Do we have more upgrades in the queue then facilities to upgrade?
          if (Get_Number_Of_Facility_Upgrades_To_Add(queue_id, item_id) < Get_Number_Of_Facility_Upgrades_In_Progress(queue_id, item_id)) then
            set remove_item := TRUE
            // Debug output
            call Sys_Debug_Print("Construction", "    - Removed " + item_name + " (Invalid Upgrade)")
          endif
        endif
      endif

      // Debug output
      call Sys_Debug_Print("Construction", "    - Building " + item_name + " (" + Sys_Convert_Long_To_String(pct_completed) + "% Complete)")

      // Attempt to remove the item(s) from our queue
      if (remove_item) or (remove_all_items) then
        if Sys_Delete_Construction_Queue_Item(queue_id, queue_item_id) then
          set list_count := list_count - 1
          set index := index - 1
          // Update our resource modifiers
          call Compute_Resource_Balances()
          call Compute_Resource_Levels()
        endif
      endif
      exitwhen (index >= list_count) or (index <= 0)
    endloop
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Compute_Spending_Resources
//------------------------------------------------------------------------
function Compute_Spending_Resources returns boolean
params
vars
  list_count:                long
  list_index:                long
  lst_queues:                longlist
  queue_id:                  long
  queue_usage:               resources
  queue_minerals:            real
  queue_organics:            real
  queue_radioactives:        real
  resources_received:        resources
  resources_stored:          resources
  resources_spent:           resources
  received_minerals:         real
  received_organics:         real
  received_radioactives:     real
  stored_minerals:           real
  stored_organics:           real
  stored_radioactives:       real
  spent_minerals:            real
  spent_organics:            real
  spent_radioactives:        real
  budget_minerals:           real
  budget_organics:           real
  budget_radioactives:       real
  debug_str:                 string
begin

  // Debug output
  call Sys_Debug_Print("Construction", "----------------------")
  call Sys_Debug_Print("Construction", "Construction - Budget:")

  // Set stop purchasing flag to false
  set gbl_stop_purchasing := FALSE

  // Get our current received, stored, and spent resources
  call resources_received.assign(Sys_Get_Player_Resources_Received_Per_Turn(sys_long_Player_ID))
  call resources_stored.assign(Compute_Resources_Stored())
  call resources_spent.assign(Compute_Resources_Spent())

  set received_minerals := resources_received.get(RESOURCE_TYPE_MINERALS)
  set received_organics := resources_received.get(RESOURCE_TYPE_ORGANICS)
  set received_radioactives := resources_received.get(RESOURCE_TYPE_RADIOACTIVES)

  set stored_minerals := resources_stored.get(RESOURCE_TYPE_MINERALS)
  set stored_organics := resources_stored.get(RESOURCE_TYPE_ORGANICS)
  set stored_radioactives := resources_stored.get(RESOURCE_TYPE_RADIOACTIVES)

  set spent_minerals := resources_spent.get(RESOURCE_TYPE_MINERALS)
  set spent_organics := resources_spent.get(RESOURCE_TYPE_ORGANICS)
  set spent_radioactives := resources_spent.get(RESOURCE_TYPE_RADIOACTIVES)

  // Determine the amount of resources to use for construction
  // Minerals
  if (bool_Race_Minerals_Low) then
    set budget_minerals := received_minerals
  endif
  if (bool_Race_Minerals_Adequate) then
    set budget_minerals := received_minerals + (stored_minerals * 0.10)
  endif
  if (bool_Race_Minerals_High) then
    set budget_minerals := received_minerals + (stored_minerals * 0.15)
  endif
  // Organics
  if (bool_Race_Organics_Low) then
    set budget_organics := received_organics
  endif
  if (bool_Race_Organics_Adequate) then
    set budget_organics := received_organics + (stored_organics * 0.10)
  endif
  if (bool_Race_Organics_High) then
    set budget_organics := received_organics + (stored_organics * 0.15)
  endif
  // Radioactives
  if (bool_Race_Radioactives_Low) then
    set budget_radioactives := received_radioactives
  endif
  if (bool_Race_Radioactives_Adequate) then
    set budget_radioactives := received_radioactives + (stored_radioactives * 0.10)
  endif
  if (bool_Race_Radioactives_High) then
    set budget_radioactives := received_radioactives + (stored_radioactives * 0.15)
  endif

  // Adjust for current expenses
  set budget_minerals := Sys_Max_Real(3000.0, budget_minerals - spent_minerals)
  set budget_organics := Sys_Max_Real(3000.0, budget_organics - spent_organics)
  set budget_radioactives := Sys_Max_Real(3000.0, budget_radioactives - spent_radioactives)

  // Set the final amount of resources to spend on construction
  call gbl_resources_to_spend.set(RESOURCE_TYPE_MINERALS, budget_minerals)
  call gbl_resources_to_spend.set(RESOURCE_TYPE_ORGANICS, budget_organics)
  call gbl_resources_to_spend.set(RESOURCE_TYPE_RADIOACTIVES, budget_radioactives)

  // Debug output
  set debug_str := Sys_Convert_Real_To_String(budget_minerals) + " Minerals, " + Sys_Convert_Real_To_String(budget_organics) + " Organics, " + Sys_Convert_Real_To_String(budget_radioactives) + " Radioactives"
  call Sys_Debug_Print("Construction", "  - Budget = " + debug_str)

  // Calculate our construction capacity
  set list_count := Sys_Get_List_Of_Players_Construction_Queues(sys_long_Player_ID, lst_queues)

  if (lst_queues.count() > 0) then
    for list_index := 1 to list_count do
      set queue_id := lst_queues.get(list_index)
      call queue_usage.assign(Sys_Get_Construction_Queue_Resource_Usage_Rate(queue_id))
      set queue_minerals := queue_minerals + queue_usage.get(RESOURCE_TYPE_MINERALS)
      set queue_organics := queue_organics + queue_usage.get(RESOURCE_TYPE_ORGANICS)
      set queue_radioactives := queue_radioactives + queue_usage.get(RESOURCE_TYPE_RADIOACTIVES)
    endfor
  endif

  // Debug output
  set debug_str := Sys_Convert_Real_To_String(queue_minerals) + " Minerals, " + Sys_Convert_Real_To_String(queue_organics) + " Organics, " + Sys_Convert_Real_To_String(queue_radioactives) + " Radioactives"
  call Sys_Debug_Print("Construction", "  - Queue Capacity = " + debug_str)

  return TRUE
end

//------------------------------------------------------------------------
// Add_Facility_Constructions
//------------------------------------------------------------------------
function Add_Facility_Constructions returns boolean
params
vars
  index:                     long
  list_count:                long
  num_items:                 long
  queue_sys_loc:             long
  queue_name:                string
  facility_space:            long
  skip_facilities:           boolean
  skip_upgrades:             boolean
begin

  // Debug output
  call Sys_Debug_Print("Construction", "--------------------------")
  call Sys_Debug_Print("Construction", "Construction - Facilities:")

  // Attempt to construct facilities for our colonies
  set list_count := lst_AI_Our_Colonies.count()

  if (list_count > 0) then
    loop
      set index := index + 1
      set gbl_queue_id := lst_AI_Our_Colonies.get(index)
      set gbl_colony_type := Sys_Get_Planet_Colony_Type(gbl_queue_id)
      set queue_sys_loc := Sys_Get_Space_Object_System_Location(gbl_queue_id)
      set queue_name := Sys_Get_Space_Object_Name(gbl_queue_id)
      set facility_space := Sys_Get_Space_Object_Facility_Space_Remaining(gbl_queue_id)
      set num_items := Sys_Get_Construction_Queue_Item_Count(gbl_queue_id)

      // Reset boolean variables
      set skip_facilities := FALSE
      set skip_upgrades := TRUE
      set gbl_queue_units_only := FALSE
      set gbl_queue_ships_only := FALSE

      // Debug output
      call Sys_Debug_Print("Construction", "  - " + queue_name)

      // Don't try to add facilities to the planet's queue if it has no space
      if (facility_space < 1000) then
        set skip_facilities := TRUE
        // Debug output
        call Sys_Debug_Print("Construction", "    - At maximum facilities")
        // Can we upgrade facilities?
        if (Can_Facilities_Be_Upgraded(gbl_queue_id)) then
          set skip_upgrades := FALSE
          // Debug output
          call Sys_Debug_Print("Construction", "       - Facilities can be upgraded")
        endif
      endif

      // Don't add more items to a queue that already has a couple of items queued
      if (num_items > 1) then
        set skip_facilities := TRUE
        // Debug output
        call Sys_Debug_Print("Construction", "    - Items queued")
      endif

      // Focus on units if our planet is low on units and enemies are present
      if Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Units") then
        if (not skip_facilities) and Is_Enemy_Present_In_System(queue_sys_loc) and (lst_AI_Enemy_System_Strengths.get(queue_sys_loc) > 500) then
          if Does_Colony_Need_More_Units(gbl_queue_id, 20) then
            set skip_facilities := TRUE
            set gbl_queue_units_only := TRUE
            // Debug output
            call Sys_Debug_Print("Construction", "    - Skip facility construction to build units")
          endif
        endif
      endif

      // If our Planet has a Space Yard and our resources are not low, consider building ships/units before facilities some of the time
      if Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Ships") then
        if (not skip_facilities) and (lst_AI_Border_System.indexof(queue_sys_loc) > 0) then
          if (not bool_Race_Maintenance_High) and (not bool_Race_Minerals_Low) and (not bool_Race_Organics_Low) and (not bool_Race_Radioactives_Low) then
            if (lst_AI_Our_Space_Yards.Indexof(gbl_queue_id) > 0) and (Sys_Get_Random_Long(1, 10) <= lng_Vehicle_Construction_Priority_Level) then
              set skip_facilities := TRUE
              set gbl_queue_ships_only := TRUE
              // Debug output
              call Sys_Debug_Print("Construction", "    - Skip facility construction to build ships")
            endif
          endif
        endif
      endif

      // Our colony should build facilities (or upgrade them) if there is available space for them
      if (not skip_facilities) or (not skip_upgrades) then
        // Debug output
        call Sys_Debug_Print("Construction", "    - Building facilities")
        call Get_Facility_Construction_Percentages()
        call Add_Constructions_From_Item_List(gbl_queue_id, 1)
      endif
      // Stop purchasing facilities or upgrades if our budgeted resources are used up
      exitwhen (gbl_stop_purchasing) or (index >= list_count)
    endloop
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Add_Constructions_From_Item_List
//------------------------------------------------------------------------
function Add_Constructions_From_Item_List returns boolean
params
  queue_id:                  long
  max_items:                 long
vars
  added_to_queue:            boolean := FALSE
  index:                     long := 0
  item_type:                 long
  item_name:                 string
  item_id:                   long
  item_cost:                 resources
  item_amount:               long
  item_cost_minerals:        real
  item_cost_organics:        real
  item_cost_radioactives:    real
  list_count:                long
  num_items:                 long := 0
  queue_name:                string
  queue_rate:                resources
  queue_usage:               resources
  queue_rate_minerals:       real
  queue_rate_organics:       real
  queue_rate_radioactives:   real
  budget_minerals:           real
  budget_organics:           real
  budget_radioactives:       real
  debug_str:                 string
begin

  // Get our queue's details
  set queue_name := Sys_Get_Space_Object_Name(queue_id)
  set queue_rate := Sys_Get_Construction_Queue_Resource_Usage_Rate(queue_id)

  // Determine the queue's construction rate for each resource type
  set queue_rate_minerals := queue_rate.get(RESOURCE_TYPE_MINERALS)
  set queue_rate_organics := queue_rate.get(RESOURCE_TYPE_ORGANICS)
  set queue_rate_radioactives := queue_rate.get(RESOURCE_TYPE_RADIOACTIVES)

  // How many items are we adding?
  set list_count := gbl_lst_item_type.count()

  // If our queue rate is zero then don't attempt to add anything
  if (queue_rate.get(RESOURCE_TYPE_MINERALS) <= 0) then
    set list_count := 0
    // Debug output
    call Sys_Debug_Print("Construction", "      - " + queue_name + " cannot build anything due to riots or no population")
  endif

  if (list_count > 0) then
    loop
      set index := index + 1
      set added_to_queue := FALSE
      set item_type := gbl_lst_item_type.get(index)
      set item_id := gbl_lst_item_id.get(index)

      // Is the item valid?
      if (item_id > 0) and (item_type > 0) then

        // Get the item's base resource cost for construction
        case item_type
          ITEM_TO_CONSTRUCT_FACILITY:
            set item_cost := Sys_Get_Facility_Cost(sys_long_Player_ID, item_id)
            set item_name := Sys_Get_Facility_Name(item_id)
          ITEM_TO_CONSTRUCT_UPGRADE_FACILITY:
            set item_cost := Sys_Get_Upgrade_Facility_Cost(sys_long_Player_ID, item_id)
            set item_name := Sys_Get_Facility_Name(item_id) + " upgrade"
          ITEM_TO_CONSTRUCT_SHIP_DESIGN:
            set item_cost := Sys_Get_Vehicle_Design_Cost(item_id)
            set item_name := Sys_Get_Vehicle_Design_Name(item_id) + " (" + Sys_Get_Vehicle_Design_Size_Name(item_id) + ")"
          ITEM_TO_CONSTRUCT_UNIT_DESIGN:
            set item_cost := Sys_Get_Vehicle_Design_Cost(item_id)
            set item_name := Sys_Get_Vehicle_Design_Name(item_id) + "(s) (" + Sys_Get_Vehicle_Design_Size_Name(item_id) + ")"
        endcase

        // How many items to add to the queue?
        set item_amount := Add_Specific_Construction_To_Queue(queue_id, index, max_items)

        if (item_amount > 0) then
          set num_items := num_items + 1
          // Get the item's cost for the number to be constructed
          set item_cost_minerals := item_cost.get(RESOURCE_TYPE_MINERALS) * item_amount
          set item_cost_organics := item_cost.get(RESOURCE_TYPE_ORGANICS) * item_amount
          set item_cost_radioactives := item_cost.get(RESOURCE_TYPE_RADIOACTIVES) * item_amount

          // Determine the queue's actual usage for each resource to construct the item
          if (item_cost_minerals > queue_rate_minerals) then
            call queue_usage.set(RESOURCE_TYPE_MINERALS, queue_rate_minerals)
          else
            call queue_usage.set(RESOURCE_TYPE_MINERALS, item_cost_minerals)
          endif
          if (item_cost_organics > queue_rate_organics) then
            call queue_usage.set(RESOURCE_TYPE_ORGANICS, queue_rate_organics)
          else
            call queue_usage.set(RESOURCE_TYPE_ORGANICS, item_cost_organics)
          endif
          if (item_cost_radioactives > queue_rate_radioactives) then
            call queue_usage.set(RESOURCE_TYPE_RADIOACTIVES, queue_rate_radioactives)
          else
            call queue_usage.set(RESOURCE_TYPE_RADIOACTIVES, item_cost_radioactives)
          endif

          if queue_usage.islessthan(gbl_resources_to_spend) then
            // Add item to queue
            case item_type
              ITEM_TO_CONSTRUCT_FACILITY:
                if Sys_Add_Facility_To_Construction_Queue(sys_long_Player_ID, queue_id, item_id) then
                  set added_to_queue := TRUE
                  // Debug output
                  call Sys_Debug_Print("Construction", "      - " + queue_name + " added a(n) " + item_name + " to its queue")
                else
                  // Debug output
                  call Sys_Debug_Print("Construction", "      - " + queue_name + " attempted to add a(n) " + item_name + " to its queue and it failed")
                endif
              ITEM_TO_CONSTRUCT_UPGRADE_FACILITY:
                for index := 1 to item_amount do
                  if Sys_Add_Facility_Upgrade_To_Construction_Queue(queue_id, item_id, 0) then
                    set added_to_queue := TRUE
                    // Debug output
                    call Sys_Debug_Print("Construction", "      - " + queue_name + " added a(n) " + item_name + " to its queue")
                  else
                    // Debug output
                    call Sys_Debug_Print("Construction", "      - " + queue_name + " attempted to add a(n) " + item_name + " to its queue and it failed")
                  endif
                endfor
              ITEM_TO_CONSTRUCT_SHIP_DESIGN:
                if Sys_Add_Vehicle_Design_To_Construction_Queue(queue_id, item_id, 1) then
                  set added_to_queue := TRUE
                  // Debug output
                  set debug_str := "    "
                  call Sys_Debug_Print("Construction", "        - " + queue_name + " added a(n) " + item_name + " to its queue")
                endif
              ITEM_TO_CONSTRUCT_UNIT_DESIGN:
                if Sys_Add_Vehicle_Design_To_Construction_Queue(queue_id, item_id, item_amount) then
                  set added_to_queue := TRUE
                  // Debug output
                  set debug_str := "    "
                  call Sys_Debug_Print("Construction", "        - " + queue_name + " added " + Sys_Convert_Long_To_String(item_amount) + " " + item_name + " to its queue")
                else
                  // Debug output
                  call Sys_Debug_Print("Construction", "      - " + queue_name + " attempted to add a(n) " + item_name + " to its queue and it failed")
                endif
            endcase
          endif

          if (added_to_queue) then
            // Update our resource budget for construction
            call gbl_resources_to_spend.subtract(queue_usage)
            // Update our budget amounts for each resource
            set budget_minerals := gbl_resources_to_spend.get(RESOURCE_TYPE_MINERALS)
            set budget_organics := gbl_resources_to_spend.get(RESOURCE_TYPE_ORGANICS)
            set budget_radioactives := gbl_resources_to_spend.get(RESOURCE_TYPE_RADIOACTIVES)
            // Debug output
            set debug_str := "      - Queue Rate = " + Sys_Convert_Real_To_String(queue_rate_minerals) + " Minerals, " + Sys_Convert_Real_To_String(queue_rate_organics) + " Organics, " + Sys_Convert_Real_To_String(queue_rate_radioactives) + " Radioactives"
            call Sys_Debug_Print("Construction", debug_str)
            set debug_str := "      - Item Cost = " + Sys_Convert_Real_To_String(item_cost_minerals) + " Minerals, " + Sys_Convert_Real_To_String(item_cost_organics) + " Organics, " + Sys_Convert_Real_To_String(item_cost_radioactives) + " Radioactives"
            call Sys_Debug_Print("Construction", debug_str)
            set debug_str := "      - Updated Budget = " + Sys_Convert_Real_To_String(budget_minerals) + " Minerals, " + Sys_Convert_Real_To_String(budget_organics) + " Organics, " + Sys_Convert_Real_To_String(budget_radioactives) + " Radioactives"
            call Sys_Debug_Print("Construction", debug_str)
            // Stop purchasing if we have no budgeted resources left
            if (budget_minerals < 200.0) or (budget_organics < 200.0) or (budget_radioactives < 200.0) then
              set gbl_stop_purchasing := TRUE
              // Debug output
              call Sys_Debug_Print("Construction", "        - Out of resources to spend on facility construction/upgrades")
            endif
          endif
        else
          if (item_amount = -1) then
            // Debug output
            call Sys_Debug_Print("Construction", "      - " + queue_name + " did not add " + item_name + " to queue due to cost")
          endif
        endif
      endif

      exitwhen (index >= list_count) or (num_items >= max_items)
    endloop
  endif

  return added_to_queue
end

//------------------------------------------------------------------------
// Add_Specific_Construction_To_Queue
//------------------------------------------------------------------------
function Add_Specific_Construction_To_Queue returns long
params
  queue_id:                  long
  item_index:                long
  max_items:                 long
vars
  index:                     long
  queue_name:                string
  queue_rate:                resources
  item_type:                 long
  item_id:                   long
  item_amount:               long
  item_cost:                 resources
  item_max_one_turn:         long
  item_max_per_loc:          long
  item_max_pct:              long
  item_size:                 long
  item_size_id:              long
  item_vehicle_type:         string
  space_needed:              long
  space_remaining:           long
  space_used:                long
  space_total:               long
  num_present:               long
  pct_present:               long
begin

  // Get our queue's details
  set queue_name := Sys_Get_Space_Object_Name(queue_id)
  set queue_rate := Sys_Get_Construction_Queue_Resource_Usage_Rate(queue_id)

  // Get the item's details
  set item_type := gbl_lst_item_type.get(item_index)
  set item_id := gbl_lst_item_id.get(item_index)
  set item_max_pct := gbl_lst_pct_of_space.get(item_index)
  set item_max_per_loc := gbl_lst_max_per_loc.get(item_index)

  if (item_id > 0) and (item_type > 0) and (item_max_pct > 0) then
    case (item_type)
      ITEM_TO_CONSTRUCT_FACILITY:
        set item_cost := Sys_Get_Facility_Cost(sys_long_Player_ID, item_id)
        set space_used := Sys_Get_Space_Object_Cargo_Facility_Tonnage_Space_Used(queue_id, item_id)
        set space_needed := Sys_Get_Facility_Tonnage_Space(sys_long_Player_ID, item_id)
        set space_remaining := Sys_Get_Space_Object_Facility_Space_Remaining(queue_id)
        set space_total := Sys_Get_Space_Object_Facility_Total_Space(queue_id)
        set num_present := Sys_Trunc(space_used / space_needed)
        set pct_present := Sys_Trunc(space_used / space_total * 100)

        // Do we have enough space or have a need for this facility?
        if (num_present <= item_max_per_loc) and (pct_present <= item_max_pct) and (space_needed <= space_remaining) then
          set item_amount := 1
        endif

        // Are there special resource considerations?
        // Low Minerals
        if (bool_Race_Minerals_Low) then
          if (item_id <> lng_facility_id_minerals) or (item_id <> lng_facility_id_spaceport) then
            if (item_cost.get(RESOURCE_TYPE_MINERALS) > 0) then
              set item_amount := 0
            endif
          endif
        endif
        // Low Organics
        if (bool_Race_Organics_Low) then
          if (item_id <> lng_facility_id_organics) or (item_id <> lng_facility_id_spaceport) then
            if (item_cost.get(RESOURCE_TYPE_ORGANICS) > 0) then
              set item_amount := 0
            endif
          endif
        endif
        // Low Radioactives
        if (bool_Race_Radioactives_Low) then
          if (item_id <> lng_facility_id_radioactives) or (item_id <> lng_facility_id_spaceport) then
            if (item_cost.get(RESOURCE_TYPE_RADIOACTIVES) > 0) then
              set item_amount := 0
            endif
          endif
        endif

      ITEM_TO_CONSTRUCT_UPGRADE_FACILITY:
        set num_present := Get_Number_Of_Facility_Upgrades_To_Add(queue_id, item_id) - Get_Number_Of_Facility_Upgrades_In_Progress(queue_id, item_id)
        set item_amount := num_present

        // Are there special resource conditions?
        // Low Minerals
        if (bool_Race_Minerals_Low) then
          if (item_id <> lng_facility_id_minerals) and (item_id <> lng_facility_id_monolith) then
            set item_amount := 0
          endif
        endif
        // Low Organics
        if (bool_Race_Organics_Low) then
          if (item_id <> lng_facility_id_organics) and (item_id <> lng_facility_id_monolith) then
            set item_amount := 0
          endif
        endif
        // Low Radioactives
        if (bool_Race_Radioactives_Low) and (item_id <> lng_facility_id_monolith) then
          if (item_id <> lng_facility_id_radioactives) then
            set item_amount := 0
          endif
        endif
        // Don't upgrade research facilities if we are at max tech
        if (bool_Race_At_Max_Tech) then
          if (item_id = lng_facility_id_research_pts) then
            set item_amount := 0
          endif
        endif

      ITEM_TO_CONSTRUCT_SHIP_DESIGN:
        set item_amount := 1

      ITEM_TO_CONSTRUCT_UNIT_DESIGN:
        set item_cost := Sys_Get_Vehicle_Design_Cost(item_id)
        set item_size := Sys_Get_Vehicle_Design_Tonnage_Space(item_id)
        set item_vehicle_type := Sys_Get_Vehicle_Size_Vehicle_Type(item_size_id)
        set item_max_one_turn := max_items
        // How many can we build in a turn?
        if (item_cost.get(RESOURCE_TYPE_MINERALS) > 0) then
          set item_max_one_turn := Sys_Min_Long(item_max_one_turn, Sys_Trunc(queue_rate.get(RESOURCE_TYPE_MINERALS) / item_cost.get(RESOURCE_TYPE_MINERALS)))
        endif
        if (item_cost.get(RESOURCE_TYPE_ORGANICS) > 0) then
          set item_max_one_turn := Sys_Min_Long(item_max_one_turn, Sys_Trunc(queue_rate.get(RESOURCE_TYPE_ORGANICS) / item_cost.get(RESOURCE_TYPE_ORGANICS)))
        endif
        if (item_cost.get(RESOURCE_TYPE_RADIOACTIVES) > 0) then
          set item_max_one_turn := Sys_Min_Long(item_max_one_turn, Sys_Trunc(queue_rate.get(RESOURCE_TYPE_RADIOACTIVES) / item_cost.get(RESOURCE_TYPE_RADIOACTIVES)))
        endif
        // Build up to a queue's rate worth of the units or a single unit if the cost is more than a turn's rate
        set item_amount := Sys_Min_Long(item_max_one_turn, max_items)
        // Consider double-dipping if the max items we want is a lot more...
        if (max_items > (item_amount * 5)) then
          set item_amount := item_amount * 2
        endif
        // Is there enough space?
        set space_remaining := Sys_Get_Space_Object_Cargo_Space_Remaining(queue_id)
        set space_needed := item_size * item_amount
        // Adjust item amount if there is not enough space
        if (space_needed > space_remaining) and (not Sys_Is_Space_Object_Base(queue_id)) then
          if (item_size > 0) then
            set item_amount := Sys_Divide_Long(space_remaining, item_size)
          endif
        endif
        // Adjust item amount if another quantity restriction is in place
        if (item_amount > max_items) then
          set item_amount := max_items
        endif
    endcase
  endif

  // Do we have enough resources in the budget to construct the item(s)
  if (item_amount > 0) then
    call item_cost.multiply(item_amount * 1.0)
    // If the item is more costly than the queue's rate, set the amount to the queue's rate
    if (item_cost.islessthan(queue_rate)) then
      // Do nothing
    else
      call item_cost.assign(queue_rate)
    endif
    // Can we afford this item?
    if item_cost.islessthan(gbl_resources_to_spend) then
      // Do nothing
    else
      set item_amount := -1
    endif
  endif

  return item_amount
end

//------------------------------------------------------------------------
// Get_Facility_Construction_Percentages
//------------------------------------------------------------------------
function Get_Facility_Construction_Percentages returns boolean
params
vars
  lst_facility_id:           longlist
  lst_facility_level:        longlist
  list_count:                long
  index:                     long
  facil_id:                  long
  facil_level:               long
  facil_count:               long
  lst_queue_items:           longlist
  queue_count:               long
  queue_index:               long
  queue_item_id:             long
  queue_item_type:           long
  research_pts:              long
  pct_research_pts:          long
  intel_pts:                 long
  pct_intel_pts:             long
  sys_id:                    long
  system_name:               string
  sys_num_facilities:        long
  planet_name:               string
  planet_size:               string
  planet_space:              long
  planet_space_left:         long
  planet_num_facilities:     long
  planet_value:              resources
  planet_minerals:           real
  planet_organics:           real
  planet_radioactives:       real
  planet_conditions:         real
  planet_breathable:         boolean := FALSE
  good_minerals:             boolean := FALSE
  good_organics:             boolean := FALSE
  good_radioactives:         boolean := FALSE
  poor_minerals:             boolean := FALSE
  poor_organics:             boolean := FALSE
  poor_radioactives:         boolean := FALSE
  poor_conditions:           boolean := FALSE
  research_focus:            boolean := FALSE
  intel_focus:               boolean := FALSE
  skip_spaceport:            boolean := FALSE
  skip_resupply_depot:       boolean := FALSE
  skip_space_yard:           boolean := FALSE
  skip_minerals:             boolean := FALSE
  temp_skip_minerals:        boolean := FALSE
  skip_minerals_mod:         boolean := FALSE
  skip_minerals_sys_mod:     boolean := FALSE
  skip_organics:             boolean := FALSE
  temp_skip_organics:        boolean := FALSE
  skip_organics_mod:         boolean := FALSE
  skip_organics_sys_mod:     boolean := FALSE
  skip_radioactives:         boolean := FALSE
  temp_skip_radioactives:    boolean := FALSE
  skip_radioactives_mod:     boolean := FALSE
  skip_radioactives_sys_mod: boolean := FALSE
  skip_monolith:             boolean := FALSE
  skip_comp_factory:         boolean := FALSE
  skip_sys_robotoid:         boolean := FALSE
  skip_resource_conversion:  boolean := FALSE
  skip_resource_reclamation: boolean := FALSE
  skip_research:             boolean := FALSE
  skip_research_pts_mod:     boolean := FALSE
  skip_research_pts_sys_mod: boolean := FALSE
  skip_intel:                boolean := FALSE
  skip_intel_pts_mod:        boolean := FALSE
  skip_intel_pts_sys_mod:    boolean := FALSE
  skip_plague_prevention:    boolean := FALSE
  skip_pop_happiness:        boolean := FALSE
  skip_pop_reproduction:     boolean := FALSE
  skip_pop_amount:           boolean := FALSE
  skip_planet_value:         boolean := FALSE
  skip_planet_conditions:    boolean := FALSE
  skip_planet_atmosphere:    boolean := FALSE
  skip_ship_training:        boolean := FALSE
  skip_fleet_training:       boolean := FALSE
  skip_shield_pts:           boolean := FALSE
  skip_sys_shield:           boolean := FALSE
  skip_minerals_storage:     boolean := FALSE
  skip_organics_storage:     boolean := FALSE
  skip_radioactives_storage: boolean := FALSE
  skip_cargo_storage:        boolean := FALSE
  skip_events_mod:           boolean := FALSE
  skip_combat_mod:           boolean := FALSE
  skip_damage_mod:           boolean := FALSE
  skip_shield_mod:           boolean := FALSE
  skip_maint_mod:            boolean := FALSE
  skip_prod_mod:             boolean := FALSE
  skip_value_mod:            boolean := FALSE
  skip_solar_resources:      boolean := FALSE
  skip_scanner:              boolean := FALSE
  skip_extra_space:          boolean := FALSE
  skip_dimensional_rift:     boolean := FALSE
  skip_allegiance_subverter: boolean := FALSE
begin

  // Get our point production
  set research_pts := Sys_Get_Empire_Current_Points(sys_long_Player_ID, POINT_TYPE_RESEARCH)
  set intel_pts := Sys_Get_Empire_Current_Points(sys_long_Player_ID, POINT_TYPE_INTELLIGENCE)

  // Get our point production percentages
  if (research_pts > 0) or (intel_pts > 0) then
    set pct_research_pts := Sys_Round(100 * research_pts / (intel_pts + research_pts))
    set pct_intel_pts := 100 - pct_research_pts
  endif

  // Get our planet's system stats
  set sys_id := Sys_Get_Space_Object_System_Location(gbl_queue_id)
  set system_name := Sys_Get_Solar_System_Name(sys_id)
  set sys_num_facilities := Get_Total_Number_Of_Facilities_In_System(sys_id)

  // Get our planet's details
  set planet_name := Sys_Get_Space_Object_Name(gbl_queue_id)
  set planet_size := Sys_Get_Planet_Size(gbl_queue_id)
  set planet_space := Sys_Get_Space_Object_Facility_Total_Space(gbl_queue_id)
  set planet_space_left := Sys_Get_Space_Object_Facility_Space_Remaining(gbl_queue_id)
  set planet_num_facilities := Get_Total_Number_Of_Facilities_On_Planet(gbl_queue_id)
  set planet_value := Sys_Get_Space_Object_Planet_Value(gbl_queue_id)
  set planet_minerals := planet_value.get(RESOURCE_TYPE_MINERALS)
  set planet_organics := planet_value.get(RESOURCE_TYPE_ORGANICS)
  set planet_radioactives := planet_value.get(RESOURCE_TYPE_RADIOACTIVES)
  set planet_conditions := Sys_Get_Planet_Conditions(gbl_queue_id)
  set planet_breathable := (not Sys_Is_Planet_Domed(gbl_queue_id))

  // Convert planet value if finite resources game
  if Sys_Is_Finite_Resource_Game() then
    // Minerals
    if (planet_minerals <= 100000) then
      set planet_minerals := 0.0
    else
      set planet_minerals := (planet_minerals / 80000) + 25
    endif
    // Organics
    if (planet_organics <= 100000) then
      set planet_organics := 0.0
    else
      set planet_organics := (planet_organics / 80000) + 25
    endif
    // Radioactives
    if (planet_radioactives <= 100000) then
      set planet_radioactives := 0.0
    else
      set planet_radioactives := (planet_radioactives / 80000) + 25
    endif
  endif

  // Note our planet's general usefulness for resources
  set good_minerals := (planet_minerals > 100)
  set good_organics := (planet_organics > 120)
  set good_radioactives := (planet_radioactives > 120)
  set poor_minerals := (planet_minerals < 80)
  set poor_organics := (planet_organics < 100)
  set poor_radioactives := (planet_radioactives < 100)

  // Clear our previous build list
  call gbl_lst_item_type.clear()
  call gbl_lst_item_id.clear()
  call gbl_lst_pct_of_space.clear()
  call gbl_lst_max_per_loc.clear()

  // Can we upgrade our existing facilities?
  call Sys_Get_Space_Object_Cargo_List_Of_Facilities(gbl_queue_id, lst_facility_id, lst_facility_level)

  set list_count := lst_facility_id.count()
  if (list_count > 0) then
    for index := 1 to list_count do
      set facil_id := lst_facility_id.get(index)
      set facil_level := lst_facility_level.get(index)
      // Add facility upgrade to the queue
      if Sys_Can_Facility_Be_Upgraded(sys_long_Player_ID, facil_id, facil_level) and (gbl_lst_item_id.indexof(facil_id) <= 0) then
        call gbl_lst_item_type.add(ITEM_TO_CONSTRUCT_UPGRADE_FACILITY)
        call gbl_lst_item_id.add(facil_id)
        call gbl_lst_pct_of_space.add(1)
        call gbl_lst_max_per_loc.add(1)
      endif
    endfor
  endif

  if (planet_space_left >= 1000) then
    // Determine which facilities to add
    set skip_spaceport                   := Is_Facility_Present_In_System(sys_id, lng_facility_id_spaceport) or Is_Facility_Queued_In_System(sys_id, "Space Port") or (lst_AI_Our_Spaceport_Systems.get(sys_id) = 1) or (lst_AI_Systems_With_Limited_Planets.indexof(sys_id) > 0)
    set skip_resupply_depot              := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_resupply_depot) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Resupply Depot") or (Sys_Get_Facility_Count_In_System(sys_long_Player_ID, sys_id, lng_facility_id_resupply_depot) > 1) or (bool_Race_Minerals_Low) or (bool_Race_Organics_Low) or (bool_Race_Radioactives_Low)
    set skip_space_yard                  := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_space_yard) or Is_Facility_Ability_Queued_On_Planet(gbl_queue_id, "Space Yard")

    // Don't build space yards on a tiny breathable planet if other space yards exist in the system
    if (not skip_space_yard) then
      set skip_space_yard                := Is_Facility_Present_In_System(sys_id, lng_facility_id_space_yard) and (planet_size = "Tiny")
    endif

    // Racial trait facilities
    set skip_events_mod                  := Is_Facility_Present_In_System(sys_id, lng_facility_id_events_mod)  or Is_Facility_Ability_Queued_In_System(sys_id, "Bad Event Chance")
    set skip_shield_mod                  := Is_Facility_Present_In_System(sys_id, lng_facility_id_shield_mod) or Is_Facility_Ability_Queued_In_System(sys_id, "Shield Modifier")
    set skip_combat_mod                  := Is_Facility_Present_In_System(sys_id, lng_facility_id_combat_mod) or Is_Facility_Ability_Queued_In_System(sys_id, "Combat Modifier")
    set skip_damage_mod                  := Is_Facility_Present_In_System(sys_id, lng_facility_id_damage_mod) or Is_Facility_Ability_Queued_In_System(sys_id, "Damage Modifier")
    set skip_maint_mod                   := Is_Facility_Present_In_System(sys_id, lng_facility_id_maint_mod) or Is_Facility_Ability_Queued_In_System(sys_id, "Ship Maintenance Cost Modifier")
    set skip_prod_mod                    := Is_Facility_Present_In_System(sys_id, lng_facility_id_prod_mod) or Is_Facility_Queued_In_System(sys_id, "Time Shrine")
    set skip_value_mod                   := Is_Facility_Present_In_System(sys_id, lng_facility_id_value_mod) or Is_Facility_Queued_In_System(sys_id, "Nature Shrine")
    set skip_solar_resources             := bool_Race_Maintenance_Low
    set skip_scanner                     := Is_Facility_Present_In_System(sys_id, lng_facility_id_scanner) or Is_Facility_Queued_In_System(sys_id, "Psychic Scanner")
    set skip_extra_space                 := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_extra_facility_space) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Interdimensional Portal Facility") or (planet_space_left <> 1000)
    set skip_dimensional_rift            := Is_Facility_Present_In_System(sys_id, lng_facility_id_dimensional_rift) or Is_Facility_Queued_In_System(sys_id, "Dimensional Rift Projector")
    set skip_allegiance_subverter        := Is_Facility_Present_In_System(sys_id, lng_facility_id_allegiance_subverter) or Is_Facility_Queued_In_System(sys_id, "Allegiance Subverter Amplifier")

    // Resource facilities
    set skip_minerals                    := bool_Race_Minerals_Prod_High and (Sys_Get_Random_Long(1, 3) = 1)
    set temp_skip_minerals               := bool_Race_Minerals_High and (bool_Race_Organics_Low or bool_Race_Radioactives_Low)
    set skip_minerals_mod                := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_minerals_mod) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Mineral Scanner")
    set skip_minerals_sys_mod            := Is_Facility_Present_In_System(sys_id, lng_facility_id_minerals_sys_mod) or Is_Facility_Queued_In_System(sys_id, "System Mineral Scanner") or (skip_prod_mod)

    set skip_organics                    := bool_Race_Organics_Prod_High and (Sys_Get_Random_Long(1, 2) = 1)
    set temp_skip_organics               := bool_Race_Organics_High and (bool_Race_Minerals_Low or bool_Race_Radioactives_Low)
    set skip_organics_mod                := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_organics_mod) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Hybrid Eco-Farms")
    set skip_organics_sys_mod            := Is_Facility_Present_In_System(sys_id, lng_facility_id_organics_sys_mod) or Is_Facility_Queued_In_System(sys_id, "System Eco-Farms") or (skip_prod_mod)

    set skip_radioactives                := bool_Race_Radioactives_Prod_High and (Sys_Get_Random_Long(1, 2) = 1)
    set temp_skip_radioactives           := bool_Race_Radioactives_High and (bool_Race_Minerals_Low or bool_Race_Organics_Low)
    set skip_radioactives_mod            := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_radioactives_mod) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Radioactives Collider")
    set skip_radioactives_sys_mod        := Is_Facility_Present_In_System(sys_id, lng_facility_id_radioactives_sys_mod) or Is_Facility_Queued_In_System(sys_id, "System Radioactives Collider") or (skip_prod_mod)

    set skip_monolith                    := not Is_Facility_Available(lng_facility_id_monolith)

    set skip_comp_factory                := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_comp_factory) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Components Factory") or (not Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_space_yard))
    set skip_sys_robotoid                := Is_Facility_Present_In_System(sys_id, lng_facility_id_sys_robotoid) or Is_Facility_Queued_In_System(sys_id, "System Robotoid Factory")
    set skip_resource_conversion         := Is_Facility_Present_In_System(sys_id, lng_facility_id_resource_conversion) or Is_Facility_Queued_In_System(sys_id, "Resource Converter")
    set skip_resource_reclamation        := Is_Facility_Present_In_System(sys_id, lng_facility_id_resource_reclamation) or Is_Facility_Queued_In_System(sys_id, "Ultra-Recycler")

    // De we need to focus more on research or intel?
    if (bool_Are_We_Computer_Player) then
      if (not bool_Race_At_Max_Tech) and (bool_Intel_Is_Allowed) then
        if (lng_Current_Pct_Intel < lng_Pct_Pts_Intel * 0.8) then
          set intel_focus := TRUE
        else
          set research_focus := TRUE
        endif
      endif
    endif

    // Research facilities
    set skip_research                    := bool_Race_At_Max_Tech or intel_focus or (temp_skip_minerals or temp_skip_organics or temp_skip_radioactives)
    set skip_research_pts_mod            := bool_Race_At_Max_Tech or Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_research_pts_mod) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Central Computer Complex")
    set skip_research_pts_sys_mod        := bool_Race_At_Max_Tech or Is_Facility_Present_In_System(sys_id, lng_facility_id_research_pts_sys_mod) or Is_Facility_Queued_In_System(sys_id, "Research Directorate")

    // Intel facilities
    set skip_intel                       := (bool_Race_At_Max_Intel and bool_Are_We_Computer_Player) or not bool_Intel_Is_Allowed or research_focus or (temp_skip_minerals or temp_skip_organics or temp_skip_radioactives)
    set skip_intel_pts_mod               := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_intel_pts_mod) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Citizen Databank Complex")
    set skip_intel_pts_sys_mod           := Is_Facility_Present_In_System(sys_id, lng_facility_id_intel_pts_sys_mod) or Is_Facility_Queued_In_System(sys_id, "Intelligence Directorate")

    // Population support facilities
    set skip_plague_prevention           := Is_Facility_Present_In_System(sys_id, lng_facility_id_plague_prevention) or Is_Facility_Ability_Queued_In_System(sys_id, "Plague Prevention")
    set skip_pop_happiness               := Is_Facility_Present_In_System(sys_id, lng_facility_id_pop_happiness) or Is_Facility_Ability_Queued_In_System(sys_id, "Planet Population Happiness")
    set skip_pop_reproduction            := Is_Facility_Present_In_System(sys_id, lng_facility_id_pop_reproduction) or Is_Facility_Ability_Queued_In_System(sys_id, "Planet Population Reproduction")
    set skip_pop_amount                  := Is_Facility_Present_In_System(sys_id, lng_facility_id_pop_amount) or Is_Facility_Ability_Queued_In_System(sys_id, "Planet Population Amount")

    // Planet modification facilities
    set skip_planet_conditions           := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_planet_conditions) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Climate Control Facility") or (planet_conditions >= 1.0)
    set skip_planet_value                := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_planet_value) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Value Improvement Plant") or (skip_value_mod) or (planet_minerals >= 150)
    set skip_planet_atmosphere           := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_planet_atmosphere) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Atmospheric Modification Plant") or (planet_breathable)
    set skip_planet_atmosphere           := skip_planet_atmosphere or ((Sys_Get_Planet_Physical_Type(gbl_queue_id) = PLANET_TYPE_GAS_GIANT) and (Get_Native_Atmosphere(sys_long_Player_ID) = ATMOSPHERE_TYPE_NONE))

    // Ship Support and shield facilities
    set skip_ship_training               := Is_Facility_Present_In_System(sys_id, lng_facility_id_ship_training) or Is_Facility_Ability_Queued_In_System(sys_id, "Ship Training")
    set skip_fleet_training              := Is_Facility_Present_In_System(sys_id, lng_facility_id_fleet_training) or Is_Facility_Ability_Queued_In_System(sys_id, "Fleet Training")
    set skip_shield_pts                  := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_shield_pts) or Is_Facility_Ability_Queued_On_Planet(gbl_queue_id, "Shield Generation")
    set skip_sys_shield                  := Is_Facility_Present_In_System(sys_id, lng_facility_id_sys_shield) or Is_Facility_Queued_In_System(sys_id, "System Gravitational Shield Facility")

    // Storage facilities
    set skip_minerals_storage            := (not bool_Race_Needs_Minerals_Storage) or (good_minerals)
    set skip_organics_storage            := (not bool_Race_Needs_Organics_Storage) or (good_organics)
    set skip_radioactives_storage        := (not bool_Race_Needs_Radioactives_Storage) or (good_radioactives)
    set skip_cargo_storage               := Is_Facility_Present_On_Planet(gbl_queue_id, lng_facility_id_cargo_storage) or Is_Facility_Queued_On_Planet(gbl_queue_id, "Cargo Facility")

    // Add a Spaceport for each system
    if (lst_AI_Our_Spaceport_Systems.get(sys_id) = 0) and (Sys_Get_System_Queues_Ability_Facility_Count(sys_long_Player_ID, sys_id, "Points Added To Empire Pool") = 0) then
      call Add_Facility_Construction_Percentage(lng_facility_id_spaceport, 100, 1, skip_spaceport)
    endif

    // Make sure there's at least one Resupply Depot in the system
    if (lst_AI_Our_Resupply_Systems.get(sys_id) = 0) and (Sys_Get_System_Queues_Ability_Facility_Count(sys_long_Player_ID, sys_id, "Supply Generation") = 0) then
      call Add_Facility_Construction_Percentage(lng_facility_id_resupply_depot, 100, 1, FALSE)
    endif

    // Add Space Yards to all our colonies that are breathable (except tiny breathable planets if there is already a space yard present elsewhere)
    if (planet_breathable) then
      call Add_Facility_Construction_Percentage(lng_facility_id_space_yard, 100, 1, skip_space_yard)
    endif

    // Add a Components Factory to our breathable planets with a Space Yard
    if (planet_breathable) and (skip_space_yard) then
      call Add_Facility_Construction_Percentage(lng_facility_id_comp_factory, 100, 1, skip_comp_factory)
    endif

    // Add a System Robotoid Factory to our systems with 3 or more Space Yards
    if (Get_Number_Of_Facilities_In_System(sys_id, lng_facility_id_space_yard) >= 3) then
      call Add_Facility_Construction_Percentage(lng_facility_id_sys_robotoid, 100, 1, skip_sys_robotoid)
    endif

    // Add an Interdimensional Portal Facility
    if (planet_breathable) or (planet_space_left = 1000) then
      call Add_Facility_Construction_Percentage(lng_facility_id_extra_facility_space, 100, 1, skip_extra_space)
    endif

    // Add a planetary modifier facility if there is enough facilities on our planet to make it worthwhile
    if (Get_Number_Of_Facilities_On_Planet(gbl_queue_id, lng_facility_id_minerals) > 5) then
      call Add_Facility_Construction_Percentage(lng_facility_id_minerals_mod, 100, 1, skip_minerals_mod)
    endif
    if (Get_Number_Of_Facilities_On_Planet(gbl_queue_id, lng_facility_id_organics) > 5) then
      call Add_Facility_Construction_Percentage(lng_facility_id_organics_mod, 100, 1, skip_organics_mod)
    endif
    if (Get_Number_Of_Facilities_On_Planet(gbl_queue_id, lng_facility_id_radioactives) > 5) then
      call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_mod, 100, 1, skip_radioactives_mod)
    endif
    if (Get_Number_Of_Facilities_On_Planet(gbl_queue_id, lng_facility_id_research_pts) > 5) then
      call Add_Facility_Construction_Percentage(lng_facility_id_research_pts_mod, 100, 1, skip_research_pts_mod)
    endif
    if (Get_Number_Of_Facilities_On_Planet(gbl_queue_id, lng_facility_id_intel_pts) > 5) then
      call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts_mod, 100, 1, skip_intel_pts_mod)
     endif

    // Add a system modifier facilities if there enough facilities in our system to make it worthwhile
    if (Get_Number_Of_Facilities_In_System(sys_id, lng_facility_id_minerals) > 10) then
      call Add_Facility_Construction_Percentage(lng_facility_id_minerals_sys_mod, 100, 1, skip_minerals_sys_mod)
    endif
    if (Get_Number_Of_Facilities_In_System(sys_id, lng_facility_id_organics) > 10) then
      call Add_Facility_Construction_Percentage(lng_facility_id_organics_sys_mod, 100, 1, skip_organics_sys_mod)
    endif
    if (Get_Number_Of_Facilities_In_System(sys_id, lng_facility_id_radioactives) > 10) then
      call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_sys_mod, 100, 1, skip_radioactives_sys_mod)
    endif
    if (Get_Number_Of_Facilities_In_System(sys_id, lng_facility_id_research_pts) > 10) then
      call Add_Facility_Construction_Percentage(lng_facility_id_research_pts_sys_mod, 100, 1, skip_research_pts_sys_mod)
    endif
    if (Get_Number_Of_Facilities_In_System(sys_id, lng_facility_id_intel_pts) > 10) then
      call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts_sys_mod, 100, 1, skip_intel_pts_sys_mod)
    endif

    // Consider other system improvement facilities depending on how many facilities we have in the system
    if (sys_num_facilities > 30) then
      call Add_Facility_Construction_Percentage(lng_facility_id_sys_shield, 100, 1, skip_sys_shield)
      call Add_Facility_Construction_Percentage(lng_facility_id_combat_mod, 100, 1, skip_combat_mod)
      call Add_Facility_Construction_Percentage(lng_facility_id_damage_mod, 100, 1, skip_damage_mod)
      call Add_Facility_Construction_Percentage(lng_facility_id_shield_mod, 100, 1, skip_shield_mod)
      call Add_Facility_Construction_Percentage(lng_facility_id_maint_mod, 100, 1, skip_maint_mod)
      call Add_Facility_Construction_Percentage(lng_facility_id_value_mod, 100, 1, skip_value_mod)
      call Add_Facility_Construction_Percentage(lng_facility_id_scanner, 100, 1, skip_scanner)
      call Add_Facility_Construction_Percentage(lng_facility_id_dimensional_rift, 100, 1, skip_dimensional_rift)
      call Add_Facility_Construction_Percentage(lng_facility_id_allegiance_subverter, 100, 1, skip_allegiance_subverter)
      call Add_Facility_Construction_Percentage(lng_facility_id_events_mod, 100, 1, skip_events_mod)
      call Add_Facility_Construction_Percentage(lng_facility_id_resource_conversion, 100, 1, skip_resource_conversion)
      call Add_Facility_Construction_Percentage(lng_facility_id_resource_reclamation, 100, 1, skip_resource_reclamation)
    endif

    if (sys_num_facilities > 20) then
      call Add_Facility_Construction_Percentage(lng_facility_id_plague_prevention, 100, 1, skip_plague_prevention)
      call Add_Facility_Construction_Percentage(lng_facility_id_pop_happiness, 100, 1, skip_pop_happiness)
      call Add_Facility_Construction_Percentage(lng_facility_id_pop_reproduction, 100, 1, skip_pop_reproduction)
      call Add_Facility_Construction_Percentage(lng_facility_id_pop_amount, 100, 1, skip_pop_amount)
      call Add_Facility_Construction_Percentage(lng_facility_id_dimensional_rift, 100, 1, skip_dimensional_rift)
    endif

    // Consider other planet improvement facilities depending on how many facilities we have on the planet
    if (planet_num_facilities > 10) then
      call Add_Facility_Construction_Percentage(lng_facility_id_shield_pts, 100, 1, skip_shield_pts)
      call Add_Facility_Construction_Percentage(lng_facility_id_planet_value, 100, 1, skip_planet_value)
      call Add_Facility_Construction_Percentage(lng_facility_id_planet_conditions, 100, 1, skip_planet_conditions)
    endif

    // Consider temporarily switching our colony type to build a needed resource facility type
    if (bool_Are_We_Computer_Player) then
      // Mining Colony
      if (gbl_colony_type = AI_STR_COLONY_TYPE_MINING) and ((bool_Race_Minerals_High) or (bool_Race_Minerals_Prod_High)) then
        if ((good_organics) and (bool_Race_Organics_Prod_Low)) or ((not poor_organics) and (bool_Race_Organics_Low)) then
          set gbl_colony_type := AI_STR_COLONY_TYPE_FARMING
        endif
        if ((good_radioactives) and (bool_Race_Radioactives_Prod_Low)) or ((not poor_radioactives) and (bool_Race_Radioactives_Low)) then
          set gbl_colony_type := AI_STR_COLONY_TYPE_REFINING
        endif
      endif
      // Farming Colony
      if (gbl_colony_type = AI_STR_COLONY_TYPE_FARMING) and ((bool_Race_Organics_High) or (bool_Race_Organics_Prod_High)) then
        if ((good_minerals) and (bool_Race_Minerals_Prod_Low)) or ((not poor_minerals) and (bool_Race_Minerals_Low)) then
          set gbl_colony_type := AI_STR_COLONY_TYPE_MINING
        endif
        if ((good_radioactives) and (bool_Race_Radioactives_Prod_Low)) or ((not poor_radioactives) and (bool_Race_Radioactives_Low)) then
          set gbl_colony_type := AI_STR_COLONY_TYPE_REFINING
        endif
      endif
      // Refining Colony
      if (gbl_colony_type = AI_STR_COLONY_TYPE_REFINING) and ((bool_Race_Radioactives_High) or (bool_Race_Radioactives_Prod_High)) then
        if ((good_minerals) and (bool_Race_Minerals_Prod_Low)) or ((not poor_minerals) and (bool_Race_Minerals_Low)) then
          set gbl_colony_type := AI_STR_COLONY_TYPE_MINING
        endif
        if ((good_organics) and (bool_Race_Organics_Prod_Low)) or ((not poor_organics) and (bool_Race_Organics_Low)) then
          set gbl_colony_type := AI_STR_COLONY_TYPE_FARMING
        endif
      endif
    endif

    // Add facilities based on colony type
    case (gbl_colony_type)

      // Our build list for a Homeworld
      AI_STR_COLONY_TYPE_HOMEWORLD:
        if (skip_research) and (skip_intel) then
          call Add_Facility_Construction_Percentage(lng_facility_id_monolith, 100, 100, skip_monolith)
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 100, skip_research)
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 100, skip_intel)
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 100, skip_minerals)
          call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 100, skip_organics)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 100, skip_radioactives)
        endif

      // Our build list for a Mining Colony
      AI_STR_COLONY_TYPE_MINING:
        // Minister for computer players
        if (bool_Are_We_Computer_Player) then
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 2, temp_skip_minerals)
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 2, skip_minerals)
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 5, skip_minerals_storage)
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 200, temp_skip_minerals)
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 5, skip_research)
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 5, skip_intel)
        // Minister for human players
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 100, temp_skip_minerals)
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 5, skip_minerals_storage)
        endif

      // Our build list for a Farming Colony
      AI_STR_COLONY_TYPE_FARMING:
        // Minister for computer players
        if (bool_Are_We_Computer_Player) then
          call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 2, temp_skip_organics)
          call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 2, skip_organics)
          call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_organics_storage)
          call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 200, temp_skip_organics)
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 5, skip_research)
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 5, skip_intel)
        // Minister for human players
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 100, temp_skip_organics)
          call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_organics_storage)
        endif

      // Our build list for a Refining Colony
      AI_STR_COLONY_TYPE_REFINING:
        // Minister for computer players
        if (bool_Are_We_Computer_Player) then
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 2, temp_skip_radioactives)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 2, skip_radioactives)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 10, 5, skip_radioactives_storage)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 200, temp_skip_radioactives)
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 5, skip_research)
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 5, skip_intel)
        // Minister for human players
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 100, temp_skip_radioactives)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 10, 5, skip_radioactives_storage)
        endif

      // Our build list for a Mining & Farming Colony
      AI_STR_COLONY_TYPE_MINING_FARMING:
        // Determine if we want more mining or farming facilities
        if (not temp_skip_minerals) and (not temp_skip_organics) then
          if (Sys_Get_Random_Long(1, 100) > lng_Minerals_Prod_Pct) then
            set temp_skip_minerals := TRUE
          else
            set temp_skip_organics := TRUE
          endif
        endif
        // Minister for computer players
        if (bool_Are_We_Computer_Player) then
          if (not skip_monolith) then
            call Add_Facility_Construction_Percentage(lng_facility_id_monolith, 100, 200, temp_skip_minerals and temp_skip_organics)
          else
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 200, temp_skip_minerals)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 200, temp_skip_organics)
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 5, skip_minerals_storage)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_organics_storage)
            call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 5, skip_research)
            call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 5, skip_intel)
          endif
        else
          // Minister for human player
          if (not skip_monolith) then
            call Add_Facility_Construction_Percentage(lng_facility_id_monolith, 100, 1, temp_skip_minerals and temp_skip_organics)
          else
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 1, temp_skip_minerals)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 1, temp_skip_organics)
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 5, skip_minerals_storage)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_organics_storage)
          endif
        endif

      // Our build list for a Mining & Refining Colony
      AI_STR_COLONY_TYPE_MINING_REFINING:
        // Determine if we want more mining or refining facilities
        if (not temp_skip_minerals) and (not temp_skip_radioactives) then
          if (Sys_Get_Random_Long(1, 100) > lng_Minerals_Prod_Pct) then
            set temp_skip_minerals := TRUE
          else
            set temp_skip_organics := TRUE
          endif
        endif
        // Minister for computer players
        if (bool_Are_We_Computer_Player) then
          if (not skip_monolith) then
            call Add_Facility_Construction_Percentage(lng_facility_id_monolith, 100, 200, temp_skip_minerals and temp_skip_radioactives)
          else
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 200, temp_skip_minerals)
            call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 200, temp_skip_radioactives)
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 5, skip_minerals_storage)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_radioactives_storage)
            call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 5, skip_research)
            call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 5, skip_intel)
          endif
        else
          // Minister for human players
          if (not skip_monolith) then
            call Add_Facility_Construction_Percentage(lng_facility_id_monolith, 100, 200, temp_skip_minerals and temp_skip_radioactives)
          else
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 200, temp_skip_minerals)
            call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 200, temp_skip_radioactives)
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 5, skip_minerals_storage)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_radioactives_storage)
          endif
        endif

      // Our build list for a Farming & Refining Colony
      AI_STR_COLONY_TYPE_FARMING_REFINING:
        // Determine if we want more farming or refining facilities
        if (not temp_skip_organics) and (not temp_skip_radioactives) then
          if (Sys_Get_Random_Long(1, 100) > lng_Organics_Prod_Pct) then
            set temp_skip_organics := TRUE
          else
            set temp_skip_radioactives := TRUE
          endif
        endif
        // Minister for computer players
        if (bool_Are_We_Computer_Player) then
          if (not skip_monolith) then
            call Add_Facility_Construction_Percentage(lng_facility_id_monolith, 100, 200, temp_skip_organics and temp_skip_radioactives)
          else
            call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 200, temp_skip_organics)
            call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 200, temp_skip_radioactives)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_organics_storage)
            call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 10, 5, skip_radioactives_storage)
            call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 5, skip_research)
            call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 5, skip_intel)
          endif
        else
          // Minister for human players
          call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 200, temp_skip_organics)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 200, temp_skip_radioactives)
          call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_organics_storage)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 10, 5, skip_radioactives_storage)
        endif

      // Our build list for a Resource Colony
      AI_STR_COLONY_TYPE_RESOURCE:
        // Determine if we want more mining, farming, or refining facilities
        if (not temp_skip_minerals) and (not temp_skip_organics) then
          if (Sys_Get_Random_Long(1, 100) > lng_Minerals_Prod_Pct) then
            set temp_skip_organics := TRUE
          else
            if (not temp_skip_radioactives) then
              if (Sys_Get_Random_Long(1, 100) > lng_Organics_Prod_Pct) then
                set temp_skip_minerals := TRUE
                set temp_skip_organics := TRUE
              else
                set temp_skip_minerals := TRUE
                set temp_skip_radioactives := TRUE
              endif
            endif
          endif
        endif
        // Minister for computer players
        if (bool_Are_We_Computer_Player) then
          if (not skip_monolith) then
            call Add_Facility_Construction_Percentage(lng_facility_id_monolith, 100, 200, FALSE)
          else
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 200, temp_skip_minerals)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 200, temp_skip_organics)
            call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 200, temp_skip_radioactives)
          endif
        else
          // Minister for human players
          if (not skip_monolith) then
            call Add_Facility_Construction_Percentage(lng_facility_id_monolith, 100, 200, FALSE)
          else
            call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 200, temp_skip_minerals)
            call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 200, temp_skip_organics)
            call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 200, temp_skip_radioactives)
          endif
        endif

      // Our build list for a Research Compound
      AI_STR_COLONY_TYPE_RESEARCH:
        if (skip_research) then
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 200, skip_intel)
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 200, skip_research)
        endif

      // Our build list for an Intelligence Compound
      AI_STR_COLONY_TYPE_INTEL:
        if (skip_intel) then
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 200, skip_research)
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 200, skip_intel)
        endif

      // Our build list for a Research & Intel Compound
      AI_STR_COLONY_TYPE_RESEARCH_INTEL:
        if (Sys_Get_Random_Long(1, 2) = 1) then
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 200, skip_research)
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 200, skip_intel)
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 200, skip_intel)
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 200, skip_research)
        endif

      // Our build list for a Resupply Base
      AI_STR_COLONY_TYPE_RESUPPLY:
        call Add_Facility_Construction_Percentage(lng_facility_id_resupply_depot, 100, 1, skip_resupply_depot)
        call Add_Facility_Construction_Percentage(lng_facility_id_space_yard, 100, 1, skip_space_yard)
        call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 1, skip_minerals_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 1, skip_organics_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 10, 1, skip_radioactives_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_maint_mod, 100, 1, skip_maint_mod)
        call Add_Facility_Construction_Percentage(lng_facility_id_resource_conversion, 100, 1, skip_resource_conversion)
        call Add_Facility_Construction_Percentage(lng_facility_id_resource_reclamation, 100, 1, skip_resource_reclamation)
        call Add_Facility_Construction_Percentage(lng_facility_id_cargo_storage, 100, 1, skip_cargo_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 2, skip_minerals_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 2, skip_organics_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 10, 2, skip_radioactives_storage)

        if (skip_research) then
          call Add_Facility_Construction_Percentage(lng_facility_id_solar_resources, 100, 10, skip_solar_resources)
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 100, skip_intel)
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_solar_resources, 100, 10, skip_solar_resources)
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 100, skip_research)
        endif

      // Our build list for a Storage Compound
      AI_STR_COLONY_TYPE_STORAGE:
        if (bool_Are_We_Computer_Player) then
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 1, skip_minerals_storage)
          call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 1, skip_organics_storage)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 10, 1, skip_radioactives_storage)
        else
          // Minister for human players
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 100, 1, skip_minerals_storage)
          call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 100, 1, skip_organics_storage)
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 100, 1, skip_radioactives_storage)
        endif
        // If the planet still has good value, also consider regular resource facilities
        if (good_minerals) then
          call Add_Facility_Construction_Percentage(lng_facility_id_minerals, 100, 200, skip_minerals)
        endif
        if (good_radioactives) then
          call Add_Facility_Construction_Percentage(lng_facility_id_radioactives, 100, 200, skip_radioactives)
        endif
        if (good_organics) then
          call Add_Facility_Construction_Percentage(lng_facility_id_organics, 100, 200, skip_organics)
        endif

      // Our build list for a Construction Yard
      AI_STR_COLONY_TYPE_CONSTRUCTION:
        call Add_Facility_Construction_Percentage(lng_facility_id_space_yard, 100, 1, skip_space_yard)
        call Add_Facility_Construction_Percentage(lng_facility_id_resupply_depot, 100, 1, skip_resupply_depot)
        call Add_Facility_Construction_Percentage(lng_facility_id_maint_mod, 100, 1, skip_maint_mod)
        call Add_Facility_Construction_Percentage(lng_facility_id_resource_reclamation, 100, 1, skip_resource_reclamation)
        call Add_Facility_Construction_Percentage(lng_facility_id_minerals_storage, 10, 5, skip_minerals_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_organics_storage, 10, 5, skip_organics_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_radioactives_storage, 10, 5, skip_radioactives_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_cargo_storage, 100, 1, skip_cargo_storage)

        if (skip_research) then
          call Add_Facility_Construction_Percentage(lng_facility_id_solar_resources, 100, 10, skip_solar_resources)
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 100, skip_intel)
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_solar_resources, 100, 10, skip_solar_resources)
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 100, skip_research)
        endif

      // Our build list for Military Installations
      AI_STR_COLONY_TYPE_MILITARY:
        call Add_Facility_Construction_Percentage(lng_facility_id_space_yard, 100, 1, skip_space_yard)
        call Add_Facility_Construction_Percentage(lng_facility_id_resupply_depot, 100, 1, skip_resupply_depot)
        call Add_Facility_Construction_Percentage(lng_facility_id_ship_training, 100, 1, skip_ship_training)
        call Add_Facility_Construction_Percentage(lng_facility_id_fleet_training, 100, 1, skip_fleet_training)
        call Add_Facility_Construction_Percentage(lng_facility_id_shield_pts, 100, 1, skip_shield_pts)
        call Add_Facility_Construction_Percentage(lng_facility_id_combat_mod, 100, 1, skip_combat_mod)
        call Add_Facility_Construction_Percentage(lng_facility_id_damage_mod, 100, 1, skip_damage_mod)
        call Add_Facility_Construction_Percentage(lng_facility_id_shield_mod, 100, 1, skip_shield_mod)
        call Add_Facility_Construction_Percentage(lng_facility_id_scanner, 100, 1, skip_scanner)
        call Add_Facility_Construction_Percentage(lng_facility_id_cargo_storage, 100, 1, skip_cargo_storage)
        call Add_Facility_Construction_Percentage(lng_facility_id_dimensional_rift, 100, 1, skip_dimensional_rift)
        call Add_Facility_Construction_Percentage(lng_facility_id_allegiance_subverter, 100, 1, skip_allegiance_subverter)

        if (skip_research) or (Sys_Get_Random_Long(1, 2) = 1 and (not skip_intel)) then
          call Add_Facility_Construction_Percentage(lng_facility_id_solar_resources, 100, 10, skip_solar_resources)
          call Add_Facility_Construction_Percentage(lng_facility_id_intel_pts, 100, 100, skip_intel)
        else
          call Add_Facility_Construction_Percentage(lng_facility_id_solar_resources, 100, 10, skip_solar_resources)
          call Add_Facility_Construction_Percentage(lng_facility_id_research_pts, 100, 100, skip_research)
        endif
    endcase
  endif

  return TRUE
end

//------------------------------------------------------------------------
// Add_Facility_Construction_Percentage
//------------------------------------------------------------------------
function Add_Facility_Construction_Percentage returns boolean
params
  facility_id:               long
  percent_of_space:          long
  max_per_loc:               long
  skip_facility:             boolean
begin
  return FALSE

  if Is_Facility_Available(facility_id) then
    if (facility_id > 0) and (not skip_facility) then
      call gbl_lst_item_type.add(ITEM_TO_CONSTRUCT_FACILITY)
      call gbl_lst_item_id.add(facility_id)
      call gbl_lst_pct_of_space.add(percent_of_space)
      call gbl_lst_max_per_loc.add(max_per_loc)
      return TRUE
    endif
  endif

end

//------------------------------------------------------------------------
// Add_Vehicle_Constructions
//------------------------------------------------------------------------
function Add_Vehicle_Constructions returns boolean
params
vars
  item_purchased:            boolean
  design_id:                 long
  size_id:                   long
  vehicle_type:              string
  design_type:               string
  sorted_queue_list:         longlist
  extra_sorted_queue_list:   longlist
  queue_id:                  long
  queue_name:                string
  queue_sys_loc:             long
  queue_sect_loc:            long
  planet_id:                 long
  num_wanted:                long
  num_empty_queues:          long
  num_items:                 long := 0
  max_items:                 long := 1
  loop_count:                long := 0
  list_count:                long
  list_index:                long
  list_pos:                  long
  index:                     long
  is_unit:                   boolean := FALSE
  is_base:                   boolean := FALSE
  is_ship:                   boolean := FALSE
  skip_queue:                boolean := FALSE
  skip_unit:                 boolean := FALSE
  temp_skip_unit:            boolean := FALSE
  skip_ship:                 boolean := FALSE
  skip_base:                 boolean := FALSE
  skip_purchasing:           boolean := FALSE
  min_minerals:              real
  min_organics:              real
  min_radioactives:          real
  budget_minerals:           real
  budget_organics:           real
  budget_radioactives:       real
begin

  // Clear previous construction list items
  call gbl_lst_item_type.clear()
  call gbl_lst_item_id.clear()
  call gbl_lst_pct_of_space.clear()
  call gbl_lst_max_per_loc.clear()

  // Get our budget resource levels
  set budget_minerals := gbl_resources_to_spend.get(RESOURCE_TYPE_MINERALS)
  set budget_organics := gbl_resources_to_spend.get(RESOURCE_TYPE_ORGANICS)
  set budget_radioactives := gbl_resources_to_spend.get(RESOURCE_TYPE_RADIOACTIVES)

  // Set our minimum resource levels
  set min_minerals := 100.0
  set min_organics := 100.0
  set min_radioactives := 100.0

  // Calculate our design stats and prepare to sort our queues
  call Sys_Compute_AI_Design_Type_Statistics(sys_long_Player_ID)
  call Sys_Prepare_For_Construction_Queue_Sort(sys_long_Player_ID)

  // Debug output
  call Sys_Debug_Print("Construction", "------------------------")
  call Sys_Debug_Print("Construction", "Construction - Vehicles:")

  // Don't build ships if are at the maximum number of ships
  if (bool_Race_At_Max_Ships) then
    set skip_ship := TRUE
    set skip_base := TRUE
    // Debug output
    call Sys_Debug_Print("Construction", "  - At the maximum number of ships")
  endif

  // Don't build units if our resources are low or we are at the maximum number of units
  if (bool_Race_Minerals_Low) or (bool_Race_Organics_Low) or (bool_Race_Radioactives_Low) or (bool_Race_At_Max_Units) then
    set skip_unit := TRUE
    // Debug output
    call Sys_Debug_Print("Construction", "  - At the maximum number of units or resources are too low for building units")
  endif

  // Don't attempt to build anything if we are at maximum number of ships and units
  if (skip_ship) and (skip_base) and (skip_unit) then
    set skip_purchasing := TRUE
  endif

  // If we have no resources left to spend, do not attempt to purchase vehicles
  if (budget_minerals <= min_minerals) or (budget_organics <= min_organics) or (budget_radioactives <= min_radioactives) then
    set skip_purchasing := TRUE
    // Debug output
    call Sys_Debug_Print("Construction", "  - Not enough resources available")
  endif

  // Determine our design types to purchase and the queues to construct them
  if (not skip_purchasing) then
    loop
      set loop_count := loop_count + 1
      set item_purchased := FALSE
      set is_unit := FALSE
      set is_ship := FALSE
      set is_base := FALSE
      set temp_skip_unit := FALSE

      // Clear our previous construction queue sort and sorted list
      call Sys_Clear_Construction_Queue_Sort_Columns()
      call sorted_queue_list.clear()

      // Skip unit construction on occasion to construct ships
      if (Sys_Get_Random_Long(1, 5) = 1) and (not skip_ship) then
        set temp_skip_unit := TRUE
        set skip_unit := TRUE
      endif

      // Debug output
      call Sys_Debug_Print("Construction", "  - Design Type Demand (" + Sys_Convert_Long_To_String(loop_count) + ")")

      // Determine the design type to purchase
      set design_type := Get_Race_Design_Type_To_Purchase(skip_unit, skip_ship, skip_base)
      set design_id := Sys_Get_Latest_Vehicle_Design_Of_AI_Type(sys_long_Player_ID, design_type)
      set size_id := Sys_Get_Vehicle_Design_Size_ID(design_id)
      set vehicle_type := Sys_Get_Vehicle_Size_Vehicle_Type(size_id)

      // Reset override to prevent unit purchase
      if (temp_skip_unit) then
        set skip_unit := FALSE
        // Debug output
        call Sys_Debug_Print("Construction", "    - Skipping unit purchase")
      endif

      // Determine the queue to add it to based on our wanted design type
      if (design_id > 0) and (not skip_purchasing) then
        call Sys_Debug_Print("Construction", "      - Empire wants to purchase a(n) " + design_type)
        // Find the best queue to build our selected unit design
        if Sys_Is_Vehicle_Design_Unit(design_id) then
          set is_unit := TRUE
          call gbl_lst_item_type.add(ITEM_TO_CONSTRUCT_UNIT_DESIGN)
          call gbl_lst_item_id.add(design_id)
          call gbl_lst_pct_of_space.add(100)
          call gbl_lst_max_per_loc.add(100)
          // Queue sort order depends on which of our colonies needs that vehicle type the most
          case vehicle_type
            "Troop":
              set list_count := lst_AI_Colony_Low_Troops.count()
              // Set sorted queue list to list of colonies with most troops needed
              if (list_count > 0) then
                for list_index := 1 to list_count do
                  call sorted_queue_list.add(lst_AI_Colony_Low_Troops.get(list_index))
                endfor
              endif
            "Fighter":
              set list_count := lst_AI_Colony_Low_Fighters.count()
              // Set sorted queue list to list of colonies with most fighters needed
              if (list_count > 0) then
                for list_index := 1 to list_count do
                  call sorted_queue_list.add(lst_AI_Colony_Low_Fighters.get(list_index))
                endfor
              endif
            "Weapon Platform":
              set list_count := lst_AI_Colony_Low_Weapon_Platforms.count()
              // Set sorted queue list to list of colonies with most Weapon Platforms needed
              if (list_count > 0) then
                for list_index := 1 to list_count do
                  call sorted_queue_list.add(lst_AI_Colony_Low_Weapon_Platforms.get(list_index))
                endfor
              endif
            "Satellite":
              set list_count := lst_AI_Colony_Low_Satellites.count()
              // Set sorted queue list to list of colonies with most Satellites needed
              if (list_count > 0) then
                for list_index := 1 to list_count do
                  call sorted_queue_list.add(lst_AI_Colony_Low_Satellites.get(list_index))
                endfor
              endif
            "Mine":
              set list_count := lst_AI_Colony_Low_Mines.count()
              // Set sorted queue list to list of colonies with most Mines needed
              if (list_count > 0) then
                for list_index := 1 to list_count do
                  call sorted_queue_list.add(lst_AI_Colony_Low_Mines.get(list_index))
                endfor
              endif
            "Drone":
              set list_count := lst_AI_Colony_Low_Drones.count()
              // Set sorted queue list to list of colonies with most Drones needed
              if (list_count > 0) then
                for list_index := 1 to list_count do
                  call sorted_queue_list.add(lst_AI_Colony_Low_Drones.get(list_index))
                endfor
              endif
          endcase
          // If no colonies with low units, sort queues by most cargo space available for low priority unit purchases
          call Sys_Add_Construction_Queue_Sort_Column(SORT_QUEUE_CARGO_SPACE_AVAILABLE, FALSE)
          call Sys_Get_Sorted_Construction_Queue_List(sys_long_Player_ID, extra_sorted_queue_list, design_id, TRUE, FALSE)
          set list_count := extra_sorted_queue_list.count()
          // Append our low priority sorted queue list to our high priority sorted queue list
          if (list_count > 0) then
            for list_index := 1 to list_count do
              call sorted_queue_list.add(extra_sorted_queue_list.get(list_index))
            endfor
          endif
        else
          // Find the best queue to build our ship or base
          if (design_type = "Base (Defense)") or (design_type = "Base (Space Yard)") then
            set is_base := TRUE
            // Sort priority: No Bases Present (Core Worlds)
            call Sys_Add_Construction_Queue_Sort_Column(SORT_QUEUE_NUM_BASES_PRESENT, TRUE)
          else
            set is_ship := TRUE
            // Sort priority: Completion time
            call Sys_Add_Construction_Queue_Sort_Column(SORT_QUEUE_COST_PER_TURN, TRUE)
            call Sys_Add_Construction_Queue_Sort_Column(SORT_QUEUE_TIME_UNTIL_COMPLETED, TRUE)
            call Sys_Add_Construction_Queue_Sort_Column(SORT_QUEUE_RESOURCE_USAGE_RATE, FALSE)
          endif
          // Execute the queue sort
          call Sys_Get_Sorted_Construction_Queue_List(sys_long_Player_ID, sorted_queue_list, design_id, FALSE, TRUE)
          call gbl_lst_item_type.add(ITEM_TO_CONSTRUCT_SHIP_DESIGN)
          call gbl_lst_item_id.add(design_id)
          call gbl_lst_pct_of_space.add(100)
          call gbl_lst_max_per_loc.add(100)
        endif

        // Look through our sorted queue list to pick the queue
        set list_count := sorted_queue_list.count()

        // Debug output
        call Sys_Debug_Print("Construction", "        - Queue sort for " + design_type)
        if (list_count > 0) then
          set list_count := Sys_Min_Long(10, list_count)
          // Print out the sorted queue list (up to the first 10)
          for list_index := 1 to list_count do
            set queue_id := sorted_queue_list.get(list_index)
            set queue_name := Sys_Get_Space_Object_Name(queue_id)
            set num_items := Sys_Get_Construction_Queue_Item_Count(queue_id)
            call Sys_Debug_Print("Construction", "          - " + queue_name + " (" + Sys_Convert_Long_To_String(num_items) + ")")
          endfor
        endif

        // Attempt to add the wanted design to one of our queues
        set list_count := sorted_queue_list.count()

        if (list_count > 0) then
          set index := 0
          set max_items := 1

          loop
            set index := index + 1
            set queue_id := sorted_queue_list.get(index)
            set queue_name := Sys_Get_Space_Object_Name(queue_id)
            set queue_sys_loc := Sys_Get_Space_Object_System_Location(queue_id)
            set num_items := Sys_Get_Construction_Queue_Item_Count(queue_id)
            set skip_queue := FALSE

            if (num_items < max_items) then
              // Don't add units to our Base Space Yards that don't have cargo space available in the same sector
              if Sys_Is_Space_Object_Base(queue_id) and (is_unit) then
                set queue_sys_loc := Sys_Get_Space_Object_System_Location(queue_id)
                set queue_sect_loc := Sys_Get_Space_Object_Sector_Location(queue_id)
                set planet_id := Get_Colony_In_Location(queue_sys_loc, queue_sect_loc)
                // Are we in the same sector as a colony and if so, is there space?
                if (planet_id = 0) or (Sys_Get_Space_Object_Cargo_Space_Remaining(planet_id) < 600) then
                  set skip_queue := TRUE
                  // Debug output
                  call Sys_Debug_Print("Construction", "            - " + queue_name + " is a Base SY and there is not enough cargo space for units in the sector")
                endif
              endif
              // Don't add items to Space Yard Ship queues
              if (Sys_Get_Space_Object_Type(queue_id) = SPACE_OBJECT_TYPE_SHIP) then
                if (not Sys_Is_Space_Object_Base(queue_id)) then
                  set skip_queue := TRUE
                endif
              endif
              // Special conditions for units
              if (not skip_queue) and (not gbl_queue_ships_only) then
                if (is_unit) and (max_items < 3) then
                  set num_wanted := 9999
                  // Attempt to construct the wanted units
                  case vehicle_type
                    "Troop":
                      if (lst_AI_Colony_Low_Troops.indexof(queue_id) > 0) then
                        set list_pos := lst_AI_Colony_Low_Troops.indexof(queue_id)
                        set num_wanted := lst_AI_Colony_Num_Troops_Wanted.get(list_pos)
                      endif
                    "Fighter":
                      if (lst_AI_Colony_Low_Fighters.indexof(queue_id) > 0) then
                        set list_pos := lst_AI_Colony_Low_Fighters.indexof(queue_id)
                        set num_wanted := lst_AI_Colony_Num_Fighters_Wanted.get(list_pos)
                      endif
                    "Weapon Platform":
                      if (lst_AI_Colony_Low_Weapon_Platforms.indexof(queue_id) > 0) then
                        set list_pos := lst_AI_Colony_Low_Weapon_Platforms.indexof(queue_id)
                        set num_wanted := lst_AI_Colony_Num_Weapon_Platforms_Wanted.get(list_pos)
                      endif
                    "Satellite":
                      if (lst_AI_Colony_Low_Satellites.indexof(queue_id) > 0) then
                        set list_pos := lst_AI_Colony_Low_Satellites.indexof(queue_id)
                        set num_wanted := lst_AI_Colony_Num_Satellites_Wanted.get(list_pos)
                      endif
                      // Build fewer Point-Defense Satellites or Recon Satellites
                      if (design_type = "Satellite (Point-Defense)") then
                        set num_wanted := Sys_Get_Random_Long(1, 3)
                      else
                        if (design_type = "Satellite (Repair)") then
                          set num_wanted := Sys_Get_Random_Long(1, 2)
                        else
                          if (design_type = "Satellite (Recon)") then
                            set num_wanted := 1
                          endif
                        endif
                      endif
                    "Mine":
                      if (lst_AI_Colony_Low_Mines.indexof(queue_id) > 0) then
                        set list_pos := lst_AI_Colony_Low_Mines.indexof(queue_id)
                        set num_wanted := lst_AI_Colony_Num_Mines_Wanted.get(list_pos)
                      endif
                    "Drone":
                      if (lst_AI_Colony_Low_Drones.indexof(queue_id) > 0) then
                        set list_pos := lst_AI_Colony_Low_Drones.indexof(queue_id)
                        set num_wanted := lst_AI_Colony_Num_Drones_Wanted.get(list_pos)
                      endif
                  endcase
                  // Add the item
                  if (num_wanted > 0) then
                    set item_purchased := Add_Constructions_From_Item_List(queue_id, num_wanted)
                  endif
                else
                  if (is_base) then
                    // Attempt to construct the wanted base only in the same sector as a core colony
                    if (lst_AI_Our_Core_Colonies.indexof(queue_id) > 0) then
                      set item_purchased := Add_Constructions_From_Item_List(queue_id, 9999)
                    endif
                  else
                    // Attempt to construct the wanted ship
                    if (not gbl_queue_units_only) then
                      set item_purchased := Add_Constructions_From_Item_List(queue_id, 9999)
                    endif
                  endif
                endif
              endif
            endif

            // If we still have resources to spend, then start stacking items in our queues
            if (index >= list_count) and (not item_purchased) then
              set index := 0
              set max_items := max_items + 1
            endif

            exitwhen (item_purchased) or (max_items >= 4)
          endloop
        endif
      else
        // Don't skip purchasing completely (due to lack of ship demand) if we're only temporarily skipping unit construction
        if (not temp_skip_unit) then
          set skip_purchasing := TRUE
        endif
        // Debug output
        call Sys_Debug_Print("Construction", "  - No demand for vehicles at this time")
      endif

      // Clear the build list
      call gbl_lst_item_type.clear()
      call gbl_lst_item_id.clear()
      call gbl_lst_pct_of_space.clear()
      call gbl_lst_max_per_loc.clear()

      // If purchase failed, do not try to add that item type again
      if (is_unit) and (not item_purchased) then
        set skip_unit := TRUE
        call Sys_Debug_Print("Construction", "  - Unit purchase failed!")
      endif
      if (is_ship) and (not item_purchased) then
        set skip_ship := TRUE
        call Sys_Debug_Print("Construction", "  - Ship purchase failed!")
      endif
      if (is_base) and (not item_purchased) then
        set skip_base := TRUE
        call Sys_Debug_Print("Construction", "  - Base purchase failed!")
      endif

      // Update our budget
      set budget_minerals := gbl_resources_to_spend.get(RESOURCE_TYPE_MINERALS)
      set budget_organics := gbl_resources_to_spend.get(RESOURCE_TYPE_ORGANICS)
      set budget_radioactives := gbl_resources_to_spend.get(RESOURCE_TYPE_RADIOACTIVES)

      // Do we still have resources to spend?
      if (budget_minerals <= min_minerals) or (budget_organics <= min_organics) or (budget_radioactives <= min_radioactives) then
        set skip_purchasing := TRUE
        // Debug output
        call Sys_Debug_Print("Construction", "  - No resources left to spend")
      endif

      // Do not try to purchase items if all purchasing has failed
      if (skip_unit) and (skip_ship) and (skip_base) then
        set skip_purchasing := TRUE
      endif

      // Quit when there are no valid items to purchase
      exitwhen (skip_purchasing) or (loop_count > 100)
    endloop
  endif

  // Debug output
  call Sys_Debug_Print("Construction", "  - Empire completed vehicle purchasing")

  call Sys_Finish_Construction_Queue_Sort()

  return item_purchased
end

//------------------------------------------------------------------------
// Get_Race_Design_Type_To_Purchase
//------------------------------------------------------------------------
function Get_Race_Design_Type_To_Purchase returns string
params
  skip_unit:                 boolean
  skip_ship:                 boolean
  skip_base:                 boolean
vars
  selected_design_type:      string := ""
  current_design_type:       string
  selected_ai_design_demand: long := 0
  current_ai_design_demand:  long
  num_wanted:                long
  num_queued:                long
  num_built:                 long
  dmd_reduction:             long
  list_count:                long
  index:                     long
  design_id:                 long
  attempt_purchase:          boolean
  debug_str:                 string
begin

  // Update our vehicle design statistics
  call Sys_Compute_AI_Design_Type_Statistics(sys_long_Player_ID)

  // Go through our design types to pick one to purchase
  set list_count := lst_AI_Design_Type_Name.Count()

  if (list_count > 0) then
    for index := 1 to list_count do
      set attempt_purchase := TRUE
      set current_design_type := lst_AI_Design_Type_Name.get(index)

      // Special adjustments for Colonizers
      if (current_design_type = "Colonizer (Rock)") or (current_design_type = "Colonizer (Ice)") or (current_design_type = "Colonizer (Gas)") then
        set num_wanted := num_wanted + lng_Num_Planets_Colonized_This_Turn
        // Debug output
        call Sys_Debug_Print("Construction", "    - Adjusted colonizers wanted by " + Sys_Convert_Long_To_String(lng_Num_Planets_Colonized_This_Turn))
      endif

      // Calculate the demand for the selected design type
      set num_wanted := lst_AI_Design_Type_Num_Wanted.get(index)
      set num_built := Sys_AI_Design_Type_Stats_Get_Vehicle_Count(current_design_type)
      set num_queued := Sys_AI_Design_Type_Stats_Get_Queue_Items_Count(current_design_type)
      set dmd_reduction := lst_AI_Design_Type_Vehicle_Demand.get(index) * (num_built + num_queued)
      set current_ai_design_demand := lst_AI_Design_Type_Vehicle_Demand.get(index) * (num_wanted) - dmd_reduction
      set design_id := Sys_Get_Latest_Vehicle_Design_Of_AI_Type(sys_long_Player_ID, current_design_type)

      // Debug output
      set debug_str := Sys_Convert_Long_To_String(current_ai_design_demand)
      set debug_str := debug_str + " (" + Sys_Convert_Long_To_String(num_wanted) + "W/" + Sys_Convert_Long_To_String(num_built) + "B/" + Sys_Convert_Long_To_String(num_queued) + "Q)"
      call Sys_Debug_Print("Construction", "    - " + current_design_type + " = " + debug_str)


      // If are Ministers for ships or units are inactive, don't try to purchase respective vehicle
      if (not Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Ships")) then
        set skip_ship := TRUE
      endif
      if (not Sys_Using_AI_Minister(sys_long_Player_ID, "Construction - Units")) then
        set skip_unit := TRUE
      endif

      // Attempt to pick the item if we have queues where it can be added
      if Sys_Is_Vehicle_Design_Unit(design_id) and (skip_unit) then
        set attempt_purchase := FALSE
      endif
      if (not Sys_Is_Vehicle_Design_Unit(design_id)) and (skip_ship) then
        set attempt_purchase := FALSE
      endif
      if (current_design_type = "Base (Defense)") or (current_design_type = "Base (Space Yard)") then
        if (skip_base) then
          set attempt_purchase := FALSE
        endif
      endif

      // Choose our design type with the greatest demand
      if (Sys_Have_Vehicle_Design_Of_AI_Design_Type(sys_long_Player_ID, current_design_type)) and (not Sys_Is_Vehicle_Design_Obsolete(design_id)) and (attempt_purchase) then
        if (current_ai_design_demand) > (selected_ai_design_demand) and (current_ai_design_demand > 0) then
          set selected_design_type := current_design_type
          set selected_ai_design_demand := current_ai_design_demand
        endif
      endif
    endfor
  endif

  return selected_design_type
end

//------------------------------------------------------------------------